泛型和枚举的学习笔记

泛型Generic

泛型类

package demo;

public class SuperArray<T> {
    
    
    private Object[] array;
    //根据下标查询数字

    //当前最后一个数字的下边,要为-1 ,以为数组的第一个下标为0
    private int currentIndex = -1;

    //构造是初始化
    public SuperArray(){
    
    
        array = new Object[8];
    }

    //添加数据的方法
    public void add(T data){
    
    
        System.out.println("我是数组的实现!---add");
        currentIndex++;
        //自动扩容
        if(currentIndex > array.length-1){
    
    
            array = dilatation(array);
        }
        array[currentIndex] = data;
    }

    public T get(int index){
    
    
        System.out.println("我是数组的实现---get");
        return (T)array[index];
    }

    //数组扩容的方法
    private Object[] dilatation(Object[] oldArray){
    
    
        Object[] newArray = new Object[oldArray.length * 2];
        for (int i = 0; i < oldArray.length; i++) {
    
    
            newArray[i] = oldArray[i];
        }
        return newArray;
    }

    //验证下标是否合法
    private boolean validateIndex(int index) {
    
    
        //只要有一个不满足就返回false
        return index <= currentIndex && index >= 0;
    }

    public static void main(String[] args) {
    
    
        SuperArray<String> superArray=new SuperArray<>();
        superArray.add("123");
        superArray.add("456");
        System.out.println(superArray.get(1));
    }
}

在类后加入,使用时声明该泛型是哪个类

泛型方法

package demo;

public class Demo1 {
    
    
    public <T> T show(T t){
    
    
        System.out.println(t);
        return t;
    }

    public static <T> T show2(T t){
    
    
        System.out.println(t);
        return t;
    }

    public static void main(String[] args) {
    
    
        Demo1 demo1 = new Demo1();
        Integer show = demo1.show(123);
        String s = Demo1.show2("123");

    }
}

方法定义要加入, 最后尽量返回泛型,如果不返回的话,相当于用Object

泛型继承

public interface Comparator<T>{
    
    
    int compare(T t1,T t2);
}
package demo;

public class User {
    
    
    private String name;
    private Integer age;

    public User() {
    
    
    }

    public User(String name, Integer age) {
    
    
        this.name = name;
        this.age = age;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public Integer getAge() {
    
    
        return age;
    }

    public void setAge(Integer age) {
    
    
        this.age = age;
    }
}

package demo;

public class UserComparator implements Comparator<User>{
    
    

    @Override
    public int compare(User t1, User t2) {
    
    
        return t1.getAge()- t2.getAge();
    }
}

package demo;

public class Test1 {
    
    
    public static void main(String[] args) {
    
    
        UserComparator userComparator=new UserComparator();
//        Comparator<User> userComparator=new UserComparator();
        int compare = userComparator.compare(new User("zs", 18), new User("ls", 16));
        System.out.println(compare);
    }
}

明确类型的泛型继承,也可以用不明确类型的,(把UserComparator替换成泛型类)

类型通配符

  • 无界(SuperArray<?> superArray)
  • 上界((SuperArray<? extends Dog> superArray) dog类及其子类都能放入数组
  • 下界 (SuperArray<? super Dog> superArray) dog类及其父类都能放入数组

类型擦除

  • 不能用类型参数替换基本类型。就比如,没有SuperArray<double>,只有SuperArray<Double>。因为当类型擦除后,SuperArray的原始类型变为Object,但是Object类型不能存储double值,只能引用Double的值

  • 泛型被擦除后,其实这两个方法是一致的,并不能构成泛型。

    image

  • 类型擦除和多态冲突 虚拟机巧妙的使用了桥方法,来解决了类型擦除和多态的冲突(类型擦除后,JVM自动补充方法把Object方法补充,区分Date的方法,来区分方法调用)

静态方法和静态类中的问题

public class Test2<T> {
    
        
    public static T one;   //编译错误    
    public static T show(T one){
    
     //编译错误    
        return null;    
    }    
}

因为泛型类中的泛型参数的实例化是在定义对象的时候指定的,而静态变量和静态方法不需要使用对象来调用。对象都没有创建,如何确定这个泛型参数是何种类型,所以当然是错误的。

public class Test2<T> {
    
        

    public static <T> T show(T one){
    
     //这是正确的    
        return null;    
    }    
}

因为这是泛型方法

枚举 enum

枚举基本特性

本质是静态常量

public class SeasonConstant {
    
    
    public static final int SPRING = 1;
    public static final int SUMMER = 2;
    public static final int AUTUMN = 3;
    public static final int WINTER = 4;
}
public enum SeasonEnum {
    
    
    SPRING,SUMMER,AUTUMN,WINTER;
}
values() 静态的自动生成的 可以遍历enum实例,其返回enum实例的数组
ordinal() 父类的实例方法 返回每个实例在声明时的次序
name() 父类的实例方法 返回enum实例声明时的名称
getDeclaringClass() 返回其所属的enum类
valueOf() 静态的自动生成的 根据给定的名称返回相应的enum实例
package demo;

public class Test1 {
    
    
    public static void main(String[] args) {
    
    
        SeasonEnum[] values = SeasonEnum.values();
        for (int i = 0; i < values.length; i++) {
    
    
            System.out.println(values[i].name());
            System.out.println(values[i].ordinal());
            System.out.println(values[i].getDeclaringClass());
            System.out.println("----------------");
        }
    }
}

Enum中添加新方法

public enum SeasonEnum {
    
    
    SPRING("春天","春暖花开的季节"),
    SUMMER("夏天","热的要命,但是小姐姐都穿短裤"),
    AUTUMN("秋天","果实成熟的季节"),
    WINTER("冬天","冷啊,可以吃火锅");

    private String name;
    private String detail;

    SeasonEnum() {
    
    
    }

    SeasonEnum(String name, String detail) {
    
    
        this.name = name;
        this.detail = detail;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public String getDetail() {
    
    
        return detail;
    }

    public void setDetail(String detail) {
    
    
        this.detail = detail;
    }
}

Switch语句中的Enum

public static void main(String[] args) {
    
    
    SeasonEnum season = SeasonEnum.SPRING;
    switch (season){
    
    
        case SPRING:
            System.out.println("春天来了,又到了万物交配的季节!");
        case SUMMER:
            System.out.println("夏天来了,又可以穿大裤衩了!");
        case AUTUMN:
            System.out.println("秋天来了,又到了收获的季节!");
        case WINTER:
            System.out.println("冬天来了,又到了吃火锅的季节了!");
        default:
            System.out.println("也没有别的季节了。");
    }
}
  • 常规情况下必须使用 enum 类型来修饰 enum 实例,但在 case 语句中不必如此,
  • 意思就是 case SPRING: 不需要写成 case SeasonEnum.SPRING:

枚举的优势

阿里《Java开发手册》对枚举的相关规定如下:

【强制】所有的枚举类型字段必须要有注释,说明每个数据项的用途。

【参考】枚举类名带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。正例:枚举名字为 ProcessStatusEnum 的成员名称:SUCCESS / UNKNOWN_REASON。

  • int 类型本身并不具备安全性,假如某个程序员在定义 int 时少些了一个 final 关键字,那么就会存在被其他人修改的风险,而反观枚举类,它“天然”就是一个常量类,不存在被修改的风险
  • 使用 int 类型的语义不够明确,比如我们在控制台打印时如果只输出 1…2…3 这样的数字,我们肯定不知道它代表的是什么含义
  • 对程序修改常量时,只需要对枚举修改,不用对所有常量进行修改

猜你喜欢

转载自blog.csdn.net/weixin_51209821/article/details/124226461