Java基础之泛型&反射

落爺英雄遲暮 提交于 2019-12-11 05:45:46

a.泛型

含义:是JDK1.5的新特性,本质是参数化类型,即所操作的数据类型被指定为一个参数,使用时通过传参来指定具体的类型。
好处:安全简单。具体体现在提供编译时的强类型检查,而不用等到运行;可避免类类型强制转换;增强代码可读性。

//不使用泛型需要强制转换
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0)
//使用泛型可避免强制转换
List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);

以上例子也能看到在集合类使用泛型的情况很普遍,而且相比于数组具有动态的特点。

类型:通过创建位置的不同,分可为

泛型类:public class 类名<泛型类型1,…>

泛型方法:public <泛型类型1,…> 返回类型 方法名(泛型类型1 参数名1,…)

泛型接口:public interface 接口名<泛型类型1,…>

下面分别举例说明。

//泛型类:把泛型定义在类上 
public class ObjectTool<T> { 
      private T obj; 
      public T getObj() { 
         return obj; 
      } 
      public void setObj(T obj) { 
           this.obj = obj;
     }
}
//测试
public class ObjectToolDemo { 
    public static void main(String[] args) { 
        ObjectTool<String> ot1 = new ObjectTool<String>();    
        ot1.setObj(new String("minmin")); 
        System.out.println("姓名是:" + ot1.getObj()); //姓名是:minmin
        ObjectTool<Integer> ot2 = new ObjectTool<Integer>();    
        ot2.setObj(new Integer(21)); 
        System.out.println("年龄是:" + ot2.getObj()); //年龄是:21
   }
}
//泛型方法:把泛型定义在方法上
public class ObjectTool {  
      public <T> T show(T t) {
          if (t != null){
              return t;
          }else{
              return null;
          }
}
//测试
public class ObjectToolDemo { 
        public static void main(String[] args) { 
            ObjectTool ot = new ObjectTool(); 
            System.out.println(ot.show("minmin"));//minmin
            System.out.println(ot.show(21));//21
       }
  }
//泛型接口:把泛型定义在接口上
public interface ObjectTool<T,U> {
    void show(T t,U u);
}
class ObjectToolTest implements ObjectTool<String,Date> {
    @Override  
    public void show(String str,Date date) {
        System.out.print(str);
        System.out.print(date);
    }
}
//测试
public class ObjectToolDemo {
    public static void main(String[] args) {  
        ObjectToolTest test = new ObjectToolTest();
        test.show("Hello",new Date());//Hello当前时间
    }    
}

泛型变量的类型限定:使用extends关键字,限定的是形式参数

如public class ObjectTool表示只接受Number类或其子类的参数

通配符?的边界限定:并配合extends和super关键字,限定的是实际参数

未受限List<?> :等效于List<? extends Object>

上边界限定List<? extends Number> :表示不确定参数类型,但一定是Number类或其子类的类型

下边界限定List<? super Number> :表示不确定参数类型,但一定是Number类或其父类的类型

如 List<? extends Number> list =new ArrayList();表示创建元素对象都是Integer的List

泛型擦除:清除泛型类型参数的相关信息,并且在必要的时候添加类型检查和类型转换的方法。即泛型java代码->普通java代码

//擦除前
class Pair<T> {
    private T value;
    public T getValue() {
        return value;
    }
    public void setValue(T  value) {
        this.value = value;
    }
}
//擦除后
class Pair {
    private Object value;
    public Object getValue() {
        return value;
    }
    public void setValue(Object  value) {
        this.value = value;
    }
}

使用限制

//不能用基本类型实例化泛型
Pair<int, char> p = new Pair<>(8, 'a');  // error
Pair<Integer, Character> p = new Pair<>(8, 'a'); // ok
//不能用static修饰泛型类型
public class MobileDevice<T> {
    private static T os; // error
}
//不能对参数化类型使用Casts,除非是无界通配符类型
List<Integer> li = new ArrayList<>();
List<?> list = li; // ok
List<Number> ln = (List<Number>) li; // error
//不能对参数化类型使用instanceof,除非是无界通配符类型
public static <E> void rtti(List<E> list) {
    if (list instanceof ArrayList<Integer>) {  // error
    }
    if (list instanceof ArrayList<?>) {  // OK
    }
}
//不能创建参数化类型的数组
ArrayList<String>[] arrayOfList = new ArrayList<String>[3]; // error
//不能创建、捕捉或抛出参数化类型的对象
class MathException<T> extends Exception {}    // error
class QueueFullException<T> extends Throwable {} // error

public static <T extends Exception, J> void execute(List<J> jobs) {
    try {
    } catch (T e) {   // error
    }
}
//不能重载参数类型为相同原始类型的方法,因为擦除后是一样的
public class Example { // error
    public void print(List<String> list) {}
    public void print(List<Integer> list) {}
}

b.反射

含义:在运行状态中,对于任意一个类都能知道它的所有属性和方法,对于任何一个对象都能够调用它的任何一个方法和属性。

功能:动态性

在运行时判断任意一个类所具有的属性和方法

在运行时判断任意一个对象所属的类

在运行时构造任意一个类的对象

在运行时调用任意一个对象的方法

生成动态代理

java.lang.Class:实现反射的基础

原因

JVM每创建一个类都会产生一个对应Class对象,并把它保存在同名.class文件。有关类加载机制
Java反射包java.lang.reflect中的所有类都没有public构造方法,只能通过Class类获得这些类的实例

获取Class对象的方法

.class:通过类的类型,基本类型可以使用

Object.getClass():通过对象实例,注意基本数据类型无法使用

Class.forName():通过类的全限定名,注意基本数据类型无法使用

Class c1 = Test.class; 
Class c2 = test.getClass();// test是Test类的一个对象
Class c3 = Class.forName("com.catchu.me.reflect.Test"); 

更多获取方法见Java反射

java.lang.reflect.Member:反射操作的对象。提供三个实现类可在运行时改变对象状态:

Constructor :对应类成员中的构造函数

Field :对应类成员中的变量

Method :对应类成员中的方法

在Class提供多种方法可以获取给定类的Constructor、Field和Method,方法如下图:
在这里插入图片描述
应用:Java反射完全解析

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!