Java 枚举类型与泛型 枚举 类型可以取代以往的常量的定义方式,即将常量封装在类或者接口中,此外,它还提供了安全检查功能。枚举类型本质上还是以类的形式存在。
泛型 的出现不仅仅可以让程序员少写某些代码,其主要作用还是解决泛型安全的问题,它提供编译时候的安全检查,不会因为将某个对象置于某个容器中而失去其类型。
枚举类型 以往的方式:
public class DayDemo { public static final int MONDAY =1 ; public static final int TUESDAY=2 ; public static final int WEDNESDAY=3 ; public static final int THURSDAY=4 ; public static final int FRIDAY=5 ; public static final int SATURDAY=6 ; public static final int SUNDAY=7 ; }
枚举出现后:
enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
枚举类型Day中分别定义了从周一到周日的值,这里要注意,值一般是大写的字母,多个值之间以逗号分隔。
使用:
public class EnumDemo { public static void main (String[] args) { Day day =Day.MONDAY; } } enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
就像上述代码那样,直接引用枚举的值即可,这便是枚举类型的最简单模型。
枚举类型的用法 用法1:常量
public enum Color { RED, GREEN, BLANK, YELLOW }
用法2:switch
enum Signal { GREEN, YELLOW, RED } public class TrafficLight { Signal color = Signal.RED; public void change () { switch (color) { case RED: color = Signal.GREEN; break ; case YELLOW: color = Signal.RED; break ; case GREEN: color = Signal.YELLOW; break ; } } }
用法3:向枚举中添加新方法
public enum Color { RED("红色" , 1 ), GREEN("绿色" , 2 ), BLANK("白色" , 3 ), YELLO("黄色" , 4 ); private String name; private int index; private Color (String name, int index) { this .name = name; this .index = index; } public static String getName (int index) { for (Color c : Color.values()) { if (c.getIndex() == index) { return c.name; } } return null ; } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getIndex () { return index; } public void setIndex (int index) { this .index = index; } }
用法4:覆盖枚举的方法
public enum Color { RED("红色" , 1 ), GREEN("绿色" , 2 ), BLANK("白色" , 3 ), YELLO("黄色" , 4 ); private String name; private int index; private Color (String name, int index) { this .name = name; this .index = index; } @Override public String toString () { return this .index+"_" +this .name; } }
用法5:实现接口
所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。
用法6:使用接口组织枚举
用法7:关于集合的使用
泛型 泛型 ,即“参数化类型” 。泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类 、泛型接口 、泛型方法 。
泛型类 public class Generic <T > { private T t; public void set (T t) { this .t = t; } public T get () { return t; } }
泛型接口 public interface Generator <T > { public T next () ; }
当实现泛型接口的类,未给泛型传入实参时:
class FruitGenerator <T > implements Generator <T > { @Override public T next () { return null ; } }
未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中。
如果不声明泛型,如:class FruitGenerator implements Generator,编译器会报错:”Unknown class”。
当实现泛型接口的类,给泛型传入了实参时
public class FruitGenerator implements Generator <String > { private String[] fruits = new String[]{"Apple" , "Banana" , "Pear" }; @Override public String next () { Random rand = new Random(); return fruits[rand.nextInt(3 )]; } }
如果类已经将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型。即:Generator,public T next();中的的T都要替换成传入的String类型。
泛型方法 public class Util { public static <K, V> boolean compare (Generic<K, V> g1, Generic<K, V> g2) { return g1.getKey().equals(g2.getKey()) && g1.getValue().equals(g2.getValue()); } } public class Generic <K , V > { private K key; private V value; public Generic (K key, V value) { this .key = key; this .value = value; } public void setKey (K key) { this .key = key; } public void setValue (V value) { this .value = value; } public K getKey () { return key; } public V getValue () { return value; } }
Util.compare()就是一个泛型方法,于是我们可以像下面这样调用泛型:
Generic<Integer, String> g1 = new Generic<>(1 , "apple" ); Generic<Integer, String> g2 = new Generic<>(2 , "pear" ); boolean same = Util.<Integer, String>compare(g1, g2);
可缩写成:
Generic<Integer, String> p1 = new Generic<>(1 , "apple" ); Generic<Integer, String> p2 = new Generic<>(2 , "pear" ); boolean same = Util.compare(p1, p2);
通配符 Generic不能被看作为Generic的子类。由此可以看出:同一种泛型可以对应多个版本(因为参数类型是不确定的),而不同版本的泛型类实例之间是不兼容的。
此时可以:
public void showKeyValue (Generic<?> obj) { System.out.println("泛型测试,value is " + obj.get()); }
此时,showKeyValue方法可以传入任意类型的Generic参数,这是一个无界的通配符。
泛型上下边界 在Java泛型定义时: 用<T>
等大写字母标识泛型类型,用于表示未知类型。 用<T extends ClassA & InterfaceB …>
等标识有界泛型,用于表示有边界的类型。 在Java泛型实例化时: 用<?>
标识通配符,用于表示实例化时的类型。 用<? extends 父类型>
标识上边界通配符,用于表示实例化时可以确定父类型的类型。 用<? super 子类型>
标识下边界通配符,用于表示实例化时可以确定子类型的类型。 对上面的Generic类增加一个新方法:
public void showKeyValue1 (Generic<? extends Number> obj) { System.out.println("泛型测试,value is " + obj.get()); }
Generic<String> generic1 = new Generic<String>("11111" ); Generic<Integer> generic2 = new Generic<Integer>(2222 ); Generic<Float> generic3 = new Generic<Float>(2.4f ); Generic<Double> generic4 = new Generic<Double>(2.56 ); showKeyValue1(generic1); showKeyValue1(generic2); showKeyValue1(generic3); showKeyValue1(generic4);
泛型的限制 1. Java泛型不能使用基本类型
2.Java泛型不允许进行直接实例化
3.Java泛型不允许进行静态化
4.Java泛型不允许直接进行类型转换(通配符可以)
5.Java泛型不允许直接使用instanceof运算符进行运行时类型检查(通配符可以)
6.Java泛型不允许创建确切类型的泛型数组(通配符可以)
7.Java泛型不允许作为参数进行重载
参考 https://www.jianshu.com/p/31b44188b973
https://www.cnblogs.com/alter888/p/9163612.html
https://www.cnblogs.com/jin-zhe/p/8259422.html