java反射

# 01 Class类 (3种实现方式)

## 一、反射

> 1、java反射机制就是在程序运行状态中,对于任意一个类,都能够知道这个类的属性和方法;对于任意一个对象,都能够调用到他的属性和方法。这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。
> 2、Class类的使用
> 3、方法的反射
> 4、成员变量的反射
> 5、构造函数的反射
> 6、Java类加载机制

## 二、Class类

> 1、万事万物皆为对象
> `那么类是谁的对象?`
> 类是对象,类是Java.lang.Class的实例对象这个对象称为该类的类类型
> 2、如创建一个Person类,创建一个实挒对象

```java
//Person的实挒对象 person表示出来了
Person person = new  Person();
```

### 1、那么Person这类是一个实挒对象,也是一个Class类的实挒对象怎么表示?

> 1、3种表示,`注意:Class有私有的构造方法,外部是无法访问的`

```java
//Class类的源码  私有的构造方法    
private Class(ClassLoader loader) {
    // Initialize final field for classLoader.  The initialization value of non-null
    // prevents future JIT optimizations from assuming this final field is null.
    classLoader = loader;    
}
```

#### 一种、类名.Class

```
//如实挒我们知道任何一个类都有一个隐藏的静态成员变量class    Class cp=Person.class;
```

#### 一种、该类的对象.getClass();

```java
//已经知道该类的对象可以通过getClass方法       
Class cp1 = person.getClass();
在这里就能把cp cp1说层是Person类的类类型
```

#### 一种、Class.forName("该的路径");

```java
Class cp3=null;        
try {            
    cp3=Class.forName("com.reflect.project.entity.Person");        
} catch (ClassNotFoundException e) {            
    e.printStackTrace();        
}
```

> 1、但是一个类只能是Class类一个实挒对象
> 如下结果都为`true`

```java
System.out.println(cp==cp1);//true
System.out.println(cp==cp3);//true
```

### 2、通过反射怎么获取方法?

```java
try {            
    Person newInstance = (Person) cp1.newInstance();              
    //可以调用无参数的构造方法  前提必须有无参数的构造方法            
    newInstance.getPerson();        
} catch (InstantiationException e) {            
    e.printStackTrace();        
} catch (IllegalAccessException e) {            
    e.printStackTrace();        
}
```

# 02 Class类动态加载类的用法

## Class类动态加载类的用法

### 一、Class.forName("类的路径")

> 1、不仅表示了类的类型,还表示了动态加载类
> 在这里要区分编译 和 运行
> 编译时加载类是静态加载类
> 运行时加载类是\*动态加载类

### 1、静态加载类

> 1、new 创建对象 是静态加载类,在编译时刻就需要加载可能使用到的类
> `问:那么我们能不能在使用到类就进行加载?`
> `答:使用动态加载类就可以完成`

```java
Teacher teacher = new Teacher();
Student Student = new Student();
```

### 2、动态加载类

> 1、Teacher 和 Student 类必须实现 Person接口 并重写start()方法

```java
//接口
public interface Person {    
    public  void start();
}
测试
@Test    
public void getTest(){        
    try {            
        Class forName = Class.forName("com.reflect.project.entity.Student");            
        Person newInstance = (Person) forName.newInstance();            
        newInstance.start();        
    } catch (Exception e) {            
        e.printStackTrace();        
    }    
}
```

# 03 Class类的使用

## Class类的使用

### 一、基本的数据类型的类类型

```java
@Test    
public void getTest1(){         
    //可以说int的类类型     
    Class in=  int.class;         
    //可以说String的类类型     
    Class str= String.class;     
    //dou 和 dou1不一样       
    Class dou= double.class;//double数据类类型     
    Class dou1=Double.class;//Double类类型     
    //打印类的名称     
    System.out.println(str.getName());     
    System.out.println(dou .getName());        
    //获取父类    
    System.out.println(dou.getSuperclass().getName());     
    //不包含包名的类名称     
    System.out.println(dou1.getSimpleName());    
}
```

# 05 Class类API 获取成员变量的信息

## 一、Class类获取方法信息

### 1、获取类的全名称

```java
@Test
public void getTest2(){    
    Class  stClass= Student.class;         
    //获取类全名称         
    System.out.println("获取类全名称>>"+stClass.getName());         
}
```

### 2、获取返回值 方法名 参数

```
一个成员方法就是一个Method对象
```

> 1、getMethods()方法是获取所有Public 修饰的方法,包括父类的
> 2、getDeclaredMethods()获取的是所有本类声明的方法,不包括父类的
> `获取返回值 方法名 参数`

```java
@Test    
public void getTest2() {        
    Class stClass = String.class;        
    Method[] methods = stClass.getMethods();        
    for (int i = 0; i < methods.length; i++) {            
        // 获取方法的返回值类型的类类型            
        Class returnType = methods[i].getReturnType();            
        System.out.print(returnType.getName() + " ");            
        // 获取方法的名称            
        System.out.print(methods[i].getName() + "(");            
        // 获取参数的类型-->参数列表的类型的类类型            
        Class[] parameterTypes = methods[i].getParameterTypes();            
        for (Class class1 : parameterTypes) {                
            System.out.print(class1.getName() + " ");            
        }            
        System.out.print(")");            
        System.out.println();        
    }    
}
```

# 06 Class类API 获构造函数的信息

## 一、获构造函数的信息

> 1、构造函数方法对象java.lang.reflect.Constructor
> 2、getConstructors()获取所有的public的构造函数
> 3、getDeclaredConstructors获取是该类声明的构造函数

### 1、获取构造函数的参数列表--得到的是参数列表的类类型

```java
@Test    
public void getTest4() {        
    Class stClass = String.class;        
    Constructor[] constructors = stClass.getConstructors();        
    Constructor[] declaredConstructors = stClass.getDeclaredConstructors();        
    for (Constructor constructor : declaredConstructors) {            
        System.out.print(constructor.getName()+"(");            
        //获取构造函数的参数列表--得到的是参数列表的类类型            
        Class[] parameterTypes = constructor.getParameterTypes();            
        for (Class class1 : parameterTypes) {                
            System.out.print(class1.getName());            
        }            
        System.out.print(")");            
        System.out.println();        
    }    
}
```

### 2、获取指定的构造函数

```java
@Test    
public void getTest7(){        
    /**         
      * 获取带两个参数(String,int)的构造方法         
      * */        
      Class personClass = Student.class;        
      try {            
          Constructor constructor  =personClass.getConstructor(String.class,int.class);            
          //需要强制转换                   
          Student per =(Student)constructor.newInstance("小张",23);           
          System.out.println(per);        
      } catch (Exception e) {            
          e.printStackTrace();        
      }    
}
```

# 07 Class类API 获取某一个方法的反射

## 一、获取某一个方法的反射

> 1、方法的操作 method.invoke(对象,参数列表)
> 2、获取方法 由名称和参数列表类决定
> 3、getMethod(name, parameterTypes) 获取的public的方法
> 4、getDeclaredMethod(name, parameterTypes) 获取自己声明的方法

### 1、获取带参数的方法

```java
@Test    
public void getTest5() {          
    Student Student = new Student();        
    Class stClass = Student.getClass();    
    try {        
        //这两种方法都可使用        
        System.out.println("----------一种---------------");        
        Method method = stClass.getMethod("start",new Class[]{int.class,int.class});        
        //如有返回就返回的对应的返回值,没有则为null        
        Object invoke = method.invoke(Student, new Object[]{1,2});        
        System.out.println(invoke);        
        System.out.println("----------二种---------------");        
        Method method1 = stClass.getMethod("start",String.class,String.class);        
        Object invoke2 = method1.invoke(Student, "小张","小组");        
        System.out.println(invoke2);    
    } catch (Exception e) {                
        e.printStackTrace();    
    }    
}
```

### 2、获取无参数的方法

```java
@Test    
public void getTest5() {          
    Student Student = new Student();        
    Class stClass = Student.getClass();    
    try {        
        System.out.println("----------一种---------------");        
        Method method4 = stClass.getMethod("start");        
        Object invoke4 = method4.invoke(Student);        
        System.out.println(invoke4);        
        System.out.println("----------二种---------------");        
        Method method3 = stClass.getMethod("start", new Class[]{});        
        Object invoke3 = method3.invoke(Student);        
        System.out.println(invoke3);    
    } catch (Exception e) {       
        e.printStackTrace();    
    }    
}
```

# 08 Class类API 通过反射越过泛型

## 一、通过反射越过泛型

> 1、泛型在编译之后会去掉泛型
> 2、集合的泛型只是在输入的时候生效,而在编译的时候有效
> 3、通过反射的方式越过泛型,就可进行添加值

```java
@Test    
public  void  getTest6(){        
    ArrayList<String> array=new ArrayList<String>();        
    array.add("小张");//只能输入String类型的        
    ArrayList array1=new ArrayList();        
    array1.add(11);         
    Class ca1=array1.getClass();         
    Class ca=array.getClass();        
    System.out.println(ca1==ca);        
    /**         
      * ca1==ca为true 说明集合的泛型只是在输入的时候生效,而在编译的时候有效         
      * 越过编译就无效了         
      * */        
    //反射进行越过泛型        
    try {            
        Method method = ca.getMethod("add", Object.class);            
        method.invoke(array, 123);            
        //array 中有字符串和数字  方式泛型是String(反射越过泛型)            
        System.err.println(array);        
    } catch (Exception e) {            
        e.printStackTrace();        
    }    
}
```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值