Java泛型与反射机制---学习笔记

Java泛型

为什么需要泛型

    List list = new ArrayList();  
    list.add("CSDN_SEU_Cavin");  
    list.add(100);  
    for (int i = 0; i < list.size(); i++) {  
      String name = (String) list.get(i); //取出Integer时,运行时出现ClassCastException异常
    System.out.println("name:" + name);  
    }  

list 集合中加入了一个字符类型的值和Integer类型的值[因为list默认类型为Object类型所以这样写合法]
为了解决这个问题,泛型才会出现

泛型的使用

List list = new ArrayList() 这样以后,list.add(100)时,引起编译错误。
通过List,直接限定了list集合中只能含有String类型的元素,从而在上例中的第5行中,无须进行强制类型转换,因为集合能够记住其中元素的类型信息,编译器已经能够确认它是String类型了。

泛型只在编译阶段有效

命名规则

E - Element (通常代表集合类中的元素)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. – 第二个,第三个,第四个类型参数……
注意,父类定义的类型参数不能被子类继承。

  • 也可以同时声明多个类型变量,用逗号分割,例如:
    public interface Pair {  
        public K getKey();  
        public V getValue();  
    }  

    public class OrderedPair implements Pair {  

        private K key;  
        private V value;  

        public OrderedPair(K key, V value) {  
          this.key = key;  
          this.value = value;  
        }  

        public K getKey()   { return key; }  
        public V getValue() { return value; }  
    }  
  • 创建了OrderedPair对象的两个实例
    Pair<String,Integer> p1 = new OrderedPair<String, Integer>("Even", 8);  
    Pair<String,String>  p2 = new OrderedPair<String, String>("hello", "world");  

    //也可以将new后面的类型参数省略,简写为:  
    //Pair p1 = new OrderedPair<>("Even", 8);  

    //也可以在尖括号内使用带有类型变量的类型变量,例如:  
    OrderedPair<String,Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));  
  • 在方法中也可是使用泛型参数,并且该参数的使用范围仅限于方法体内
    public class Util {  
    //该方法用于比较两个Pair对象是否相等。  
    //泛型参数必须写在方法返回类型boolean之前  
        public static <K, V> boolean compare(Pair<K,V> p1, Pair<K, V> p2) {  
            return p1.getKey().equals(p2.getKey())&&  
                  p1.getValue().equals(p2.getValue());  
        }  
    }  

    Pair<Integer,String> p1 = new Pair<>(1, "apple");  
    Pair<Integer,String> p2 = new Pair<>(2, "pear");  
    boolean same = Util.<Integer, String>compare(p1, p2);  
    //实际上,编译器可以通过Pair当中的类型来推断compare需要使用的类型,所以可以简写为:  
    // boolean same= Util. compare(p1, p2);  

泛型类的继承

  • Integer是Object的子类
  • Integer是Number的子类
  • Double是Number的子类
  • 容易混淆的
/该方法接受的参数类型为Box<Number>  
public void boxTest(Box<Number> n) {  
……  
}  
//下面两种调用都会报错  
boxTest(Box<Integer>);  
boxTest(Box);  

虽然Integer和Double都是Number的子类,但是Box与Box并不是Box的子类,不存在继承关系。Box与Box的共同父类是Object。

通配符

    public void boxTest(Box n){  
                 ……  
    }  

该方法只能接受 Box 这种类型的参数,因此用到了通配符

  • 为了该方法可以接受Number以及它的任何子类
    public void boxTest(Box n){  
                 ……  
    }  

? extends Number ”就代表可以接受Number以及它的子类作为参数。这种声明方式被称为上限通配符(upper bounded wildcard)。

  • 希望该方法可以接受Integer,Number以及Object类型的参数
    public void boxTest(Boxsuper Integer> n){  
            ……  
    }  

? super Integer ”代表可以接受Integer以及它的父类作为参数。这种声明方式被称为下限通配符(lower bounded wildcard)。

  • 如果类型参数中既没有extends 关键字,也没有super关键字,只有一个?,代表无限定通配符(Unbounded Wildcards)。
    • 通常在两种情况下会使用无限定通配符:
      • 如果正在编写一个方法,可以使用Object类中提供的功能来实现
      • 代码实现的功能与类型参数无关,比如List.clear()与List.size()方法,还有经常使用的Class
例子:

Java泛型与反射机制---学习笔记_第1张图片

上限通配符、下限通配符、无限定通配符之间的关系:

Java泛型与反射机制---学习笔记_第2张图片

java的反射机制

什么是反射机制

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射机制能做什么

反射机制主要提供了以下几个功能:

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法
  • 生成动态代理

具体功能实现

反射机制获取类有三种方法,我们来获取Employee类型

//第一种方式:  
Classc1 = Class.forName("com.app.XXX.Employee");  
//第二种方式:  
//java中每个类型都有class 属性.  
Classc2 = Employee.class;  

//第三种方式:  
//java语言中任何一个java对象都有getClass 方法  
Employee e = new Employee();  
Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee) 

获取所有的方法:getMethods();

  • Method[] methods = class1.getMethods();

获取所有实现的接口:getInterfaces();

  • Class[] in = class1.getInterfaces();

获取父类:getSuperclass();

  • Class superclass = class1.getSuperClass();

获取所有的构造函数:getConstructors();

  • Constructor[] constructors = class1.getConstructors() ;

获取所有的属性:getDeclaredFields();

  • Field[] field = class1.getDeclaredFields();
    • 可以看出属性的修饰符是: private(会变) , 数据类型:String (会变),名字:id/name(会变)
  • getDeclaredFields();getFields(); 的区别
    • getDeclaredFields():获得某个类的所有申明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
    • getFields():获得某个类的所有的公共(public)的字段,包括父类。
  • field.setAccessible(true); ===>例:private 类型 无法做出修改 所以设置这个 就可以了

    • 打破封装 实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问
    • 由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的

    Java泛型与反射机制---学习笔记_第3张图片

创建对象:获取类以后我们来创建它的对象,利用newInstance:

//创建类
Class class1 = Class.forName("com.app.Person");
//创建实例化:相当于 new 了一个对象
Object object = class1.newInstance() ;
//向下转型
Person person = (Person) object ;

总结

  • 首先根据传入的类的全名来创建Class对象
    • Class c = Class.forName(“className”);//className必须为全名 也就是包含包名,比如:cn.netjava.pojo.UserInfo
    • Object obj = c.newInstance();//创建对象的实例

有了对象之后 想要什么信息 就可以得到什么信息了

  • Class类提供了四个public方法,用于获取某个类的构造方法。

    • Constructor getConstructor(Class[] params) 根据构造函数的参数,返回一个具体的具有public属性的构造函数(根据指定参数获得public构造方法)
    • Constructor[] getConstructors() 返回所有具有public属性的构造函数数组(获得public的所有构造方法)
    • Constructor getDeclaredConstructor(Class[] params) 根据构造函数的参数,返回一个具体的构造函数(根据指定参数获得public和非public的构造方法)
    • Constructor[] getDeclaredConstructors() 返回该类中所有的构造函数数组(获得public的所有构造方法)
  • 四种获取成员方法的方法

    • Method getMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的具有public属性的方法(根据方法名 参数类型获得方法)
    • Method[] getMethods() 返回所有具有public属性的方法数组(获取所有的public方法)
    • Method getDeclaredMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的方法(根据方法名和参数类型,获得public和非public的方法)
    • Method[] getDeclaredMethods() 返回该类中的所有的方法数组(不分public和非public属性)
  • 四种获取成员属性的方法

    • Field getField(String name) 根据变量名,返回一个具体的具有public属性的成员变量(根据变量名得到相应的public变量)
    • Field[] getFields() 返回具有public属性的成员变量的数组(获得类中所有public的方法)
    • Field getDeclaredField(String name) 根据变量名,返回一个成员变量(根据方法名获得public和非public的变量)
    • Field[] getDelcaredField() 返回所有成员变量组成的数组(获取类中所有的public和非public的方法)
      “`

利用反射机制能获得什么信息

Java泛型与反射机制---学习笔记_第4张图片

学习来源

java泛型详解
java的反射机制浅谈
Java 反射 使用总结

你可能感兴趣的:(Java学习笔记)