多态:

是指同一行为,具有多个不同表现形式。

生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也
是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。

发生的条件

  1. 继承或者实现
  2. 方法的重写 (表现行为形式不同)
  3. 父类引用指向子类对象(格式的体现)
    格式
父类 对象名 = new 子类()

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后方法。

public abstract class Animal {
    public abstract void eat();
}
public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("喵喵的吃");
    }
}

public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("康康的吃");
    }
}

public class Test {
    public static void main(String[] args) {
        // 多态形式创建对象
        // 父类 对象名 = new 子类()
        Animal cat = new Cat();
        cat.eat();

    }
}

多态好处

package com.huyuhang.day07.whyduotai;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class Test {
    public static void main(String[] args) {
        Test test = new Test();
        List<Integer> list1 = test.genArray(10);
        List<Integer> list2 = test.genArray2(10);
        System.out.println(list1);
        System.out.println(list2);
        System.out.println(test.getMax(list1));
        System.out.println(test.getMax(list2));
    }
    public int getMax(List<Integer> list){
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i) > max)
                max = list.get(i);
        }
        return max;
    }
    
//
//    public int getMax(ArrayList<Integer> list){
//        int max = Integer.MIN_VALUE;
//        for (int i = 0; i < list.size(); i++) {
//            if (list.get(i) > max)
//                max = list.get(i);
//        }
//        return max;
//    }
//    public int getMax(LinkedList<Integer> list){
//        int max = Integer.MIN_VALUE;
//        for (int i = 0; i < list.size(); i++) {
//            if (list.get(i) > max)
//                max = list.get(i);
//        }
//        return max;
//    }

    public ArrayList<Integer> genArray(int n){
        Random random = new Random();
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            list.add(random.nextInt(100));
        }
        return list;
    }
    public LinkedList<Integer> genArray2(int n){
        Random random = new Random();
        LinkedList<Integer> list = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            list.add(random.nextInt(100));
        }
        return list;
    }
}

笔记本电脑案例

public interface USB {
    void  open();//开启
    void  close();//关闭
}
public class Mouse implements USB{
    @Override
    public void open() {
        System.out.println("鼠标连接成功, 小红灯闪闪闪");
    }

    @Override
    public void close() {
        System.out.println("鼠标断开成功, 小红灯灭灭灭");

    }
   public void click(){
        System.out.println("鼠标单击");
    }
}
public class KeyBoard implements USB{

    @Override
    public void open() {
        System.out.println("键盘连接成功, 小绿灯闪闪闪");
    }

    @Override
    public void close() {
        System.out.println("键盘断开成功, 小绿灯灭灭灭");

    }
    public void type(){
        System.out.println("键盘打字");
    }
}

public class Laptop {
    public void run(){
        System.out.println("笔记本运行");
    }
    // 使用USB设备 传入一个符合USB标准的类
    public void useUSB(USB usb){
        if (usb !=null){
            usb.open();
            // 判断传进来的数据类型
            if (usb instanceof Mouse){
                // 向下转型
                Mouse mouse =  (Mouse) usb;
                mouse.click();
            }else if (usb instanceof KeyBoard){
                KeyBoard keyBoard =  (KeyBoard) usb;
                keyBoard.type();
            }
            usb.close();
        }

    }
//    public void useUSB(KeyBoard keyBoard){
//        keyBoard.open();
//        keyBoard.type();
//        keyBoard.close();
//    }
//    public void useUSB(Mouse mouse){
//        mouse.open();
//        mouse.click();
//        mouse.close();
//    }
    public void shutDown(){
        System.out.println("笔记本关闭");
    }
}

public class Test {

    public static void main(String[] args) {
        Laptop laptop = new Laptop();
        laptop.run();
        // 向上转型
        USB mouse = new Mouse();
        laptop.useUSB(mouse);
        USB keyBoard = new KeyBoard();
        laptop.useUSB(keyBoard);
        laptop.shutDown();

    }
}

权限修饰符

public:公共的。

protected:受保护的

default:默认的

private:私有的

java中多态的表现 java中多态的表现形式_List


可见,public具有最大权限。private则是最小权限。

编写代码时,如果没有特殊的考虑,建议这样使用权限:

  • 成员变量使用private,隐藏细节。
  • 构造方法使用public,方便创建对象。
  • 成员方法使用public方便调用方法。
  • 不加权限修饰符,其访问能力与default修饰符相同

内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。

public class Car {
    class Engine{
        // 内部类
    }
}

特点

  • 内部类可以直接访问外部类的成员,包括私有成员
  • 外部类要访问内部类的成员,必须要建立内部类的对象。
package com.claire.day09.duotai;

public class Person {
    private  boolean live = true;


    class Heart{
        public void jump(){
            // 直接访问外部类成员
            if (live)
                System.out.println("心脏在跳动");
            else
                System.out.println("心脏不动了");
        }


    }

    public boolean isLive() {
        return live;
    }

    public void setLive(boolean live) {
        this.live = live;
    }

}

匿名内部类

匿名内部类:是内部类的简化写法。它的本质是一个带具体实现的
父类或者父接口的匿名的子类对象。
开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步操作,

  • 定义子类
  • 重写接口中的方法
  • 创建子类对象
  • 调用重写后的方法
匿名内部类必须继承一个父类或者实现一个父接口。
public abstract class FlyAble {
   public abstract void  fly();
}

public static void main(String[] args) {
       FlyAble f =  new FlyAble() {
           @Override
           public void fly() {
               System.out.println("飞飞飞");
           }
       };
       f.fly();
   }

Collection、List、泛型

  • 集合:集合是java中提供的一种容器,可以用来存储多个引用数据类型的数据。

集合和数组既然都是容器,它们有什么区别呢?

  • 数组的长度是固定的。集合的长度是可变的。
  • 集合存储的都是引用数据类型。如果想存储基本类型数据需要存储对应的包装类类型。

单列集合常用类的继承体系

Collection:是单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是

  • java.util.List: List的特点是元素有序、元素可重复 ;
  • List接口的主要实现类有java.util.ArrayList和java.util.LinkedList,
  • java.util.Set: Set的特点是无序, 元素不可重复。
  • Set接口的主要实现类有java.util.HashSet和java.util.LinkedHashSet,java.util.TreeSet。

java中多态的表现 java中多态的表现形式_开发语言_02



  • 注意:上面这张图只是我们常用的集合有这些,不是说就只有这些集合。
单列集合常用类的继承体系:
	Collection集合:接口,是所有单列集合的顶层父接口,该集合中的方法可以被所有单列集合共享
    	List集合: 接口,元素可重复,元素有索引,元素存取有序
        	ArrayList集合: 实现类,查询快,增删慢
            LinkedList集合: 实现类,查询慢,增删快

        Set集合: 接口, 元素不可重复(唯一),元素无索引
            HashSet集合: 实现类,元素存取无序
            LinkedHashSet集合:实现类,元素存取有序
            TreeSet集合:实现类,可以对集合中的元素进行排序

Collection 常用功能

Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。
Collection是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法如下:

  • public boolean add(E e): 把给定的对象添加到当前集合中 。
  • public void clear() :清空集合中所有的元素。
  • public boolean remove(E e): 把给定的对象在当前集合中删除。
  • public boolean contains(Object obj): 判断当前集合中是否包含给定的对象。
  • public boolean isEmpty(): 判断当前集合是否为空。
  • public int size(): 返回集合中元素的个数。
  • public Object[] toArray(): 把集合中的元素,存储到数组中
package com.claire.day11.collect;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

public class Test1 {
    public static void main(String[] args) {
        Collection<String> col = new ArrayList<>(); // 多态

        col.add("小鲁班");
        col.add("妲己");
        col.add("后羿");

        System.out.println("Collection = " + col);

        col.remove("妲己");
//        col.clear();
        System.out.println("Collection remove = " + col);

        System.out.println(col.contains("后羿"));
        System.out.println(col.contains("妲己"));
        System.out.println(col.isEmpty());
        System.out.println(col.size());  // 元素个数

        Object[] array = col.toArray();
        String[] arr1 = new String[6];
        System.out.println(array);
        System.out.println(Arrays.toString(array));

    }
}

Iterator迭代器

迭代的概念

迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续再判断,如果还有就再取出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

Collection集合提供了一个获取迭代器的方法:
Iterator iterator(); 获取集合对应的迭代器,用来遍历集合中的元素的。

Iterator接口的常用方法

  • public E next():返回迭代的下一个元素。
  • public boolean hasNext():如果仍有元素可以迭代,则返回 true。
public static void main(String[] args) {
        Collection<String> col = new ArrayList<>(); // 多态

        col.add("小鲁班");
        col.add("妲己");
        col.add("后羿");
        Iterator<String> iterator = col.iterator();
        while (iterator.hasNext()){
            String s = iterator.next();
            System.out.print(s +"\t");
        }

    }

增强for

增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。

for(元素的数据类型  变量 : Collection集合or数组){ 
  	//写操作代码
}
package com.claire.day11.collect;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Test3 {
    public static void main(String[] args) {
        Collection<String> col = new ArrayList<>(); // 多态

        col.add("小鲁班");
        col.add("妲己");
        col.add("后羿");

        for(String hero:col){
            System.out.println(hero);
        }

        int[] arr = {1, 2, 3, 4, 45, 5};
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

        System.out.println("++++++++++++++++");
        for (int num: arr){
            System.out.println(num);
        }

    }
}

泛型

  • 定义的时候表示一种未知的数据类型,在使用的时候确定其具体的数据类型。

tips:泛型的作用是在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object

定义和使用含有泛型的类

定义含有泛型的类

修饰符 class 类名<代表泛型的变量> {  }
代表泛型的变量: 可以是任意字母  例如: T,E...
public class ArrayList<E>{
  public boolean add(E e);
}

泛型在定义的时候不具体类型,使用的时候才具体类型。在使用的时候确定泛型的具体数据类型。

package com.huyuhang.day08;

public class MyList<E> {
    // 存储数据的原始数组
    private E[] data;
    // 存储有效元素的个数
    private int size ;

    public MyList(int capacity) {
        data = (E[])new Object[capacity];
        size = 0;
    }
    public MyList() {
        this(10);
    }

    private void add(int index, E e){
        for (int i = size-1; i >= index ; i--) {
            data[i+1] = data[i];
        }
        data[index] = e;
        size++;
    }
    public void add(E e){
        add(size, e);
    }
    
    public E get(int index){
        return data[index];
    }
    
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < size; i++) {
            sb.append(data[i]);
            if (i != size -1)
                sb.append(", ");
        }
        sb.append("]");
        return sb.toString();
    }
}

测试

package com.huyuhang.day08;

import java.util.ArrayList;
import java.util.List;

public class TestMyList {
    public static void main(String[] args) {
        MyList<Integer> myList = new MyList();
        myList.add(11);
        myList.add(22);
        myList.add(33);
        myList.add(88);
        System.out.println(myList);
        MyList<String> myList2 = new MyList();
        myList2.add("aaa");
        myList2.add("bbb");
        myList2.add("cccc");
        myList2.add("ddd");
        System.out.println(myList2);
        MyList<Student> list = new MyList();
        list.add(new Student("张三", 18, 99.9));
        list.add(new Student("李四", 23, 69.9));
        list.add(new Student("王五", 44, 89.9));
        System.out.println(list);

    }

}

定义和使用含有泛型的方法

修饰符 <代表泛型的变量> 返回值类型 方法名(参数){  }
public class MySort {

    public static <E>  void swap(E[] arr, int i, int j){
        E t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }
}
public class TestMysort {
    public static void main(String[] args) {
        Integer[] arr = {1, 4, 2, 6, 5, 3};
        MySort.swap(arr, 0, 3);
        System.out.println(Arrays.toString(arr));
    }
}

定义和使用含有泛型的接口

修饰符 interface接口名<代表泛型的变量> {  }
定义实现类时确定泛型的类型

接口

public interface IA<E>{
    public void method1(E e);
    public default E method2(E e){
        return e;
    }
}

实现类
实现的时候就确定类型

public class Impl1 implements IA<String>{

    @Override
    public void method1(String s) {
        System.out.println(s);
    }
}
始终不确定泛型的类型,直到创建对象时,确定泛型的类型
public class Impl2<E> implements IA<E>{

    @Override
    public void method1(E e) {
        System.out.println(e);
    }

    public static void main(String[] args) {
        // 创建对象 的时候再确定
        Impl2<String> impl2 = new Impl2<>();
        impl2.method1("哈哈");
    }
}

泛型是一种未知的数据类型,定义在类上的泛型,使用类的时候会确定泛型的类型,定义在方法上的泛型,会在使用方法的时候确定泛型,定义在接口上的泛型,需要使用接口的时候确定泛型。

小结

泛型:定义的时候表示一种未知的数据类型,在使用的时候确定其具体的数据类型。
使用含有泛型的类: 创建该类对象的时候,指定泛型的具体数据类型
使用含有方向的方法: 调用该方法的时候,确定泛型的具体数据类型
使用含有泛型的接口:
1.创建实现类实现接口的时候,指定泛型的具体数据类型
2.创建实现类实现接口的时候,不知道泛型的具体数据类型,而是创建实现类对象的时候指定泛型的具体数据类型