## Java反射
[TOC]
### Class类的使用
> There is a class named Class。在面向对象的世界里,万事万物皆对象。在Java语言里,
> 1. 面向对象的世界里,万事万物皆对象。Java中,静态成员、普通数据类型不是对象。类是谁的对象?类是对象,类是`java.lang.class`类对象
>
> ```
> There is a class named Class
> ```
>
> 2. 任何一个类都是Class的实例对象,这个实例对象有三种表达方式(假设这个类为`com.test.Foo`)
>
> - `Class c1 = Foo.class ` (任何一个类都有一个隐含的静态对象)
> - `Class c2 = foo1.getClass()` (通过实例的`getClass()`方法)
> - `Class c3=Class.forName("com.test.Foo")` (通过`Class.forName()`)
>
> 不管使用何种方式`c1==c2==c3`,为该类的类类型(`class type`)。我们可以通过`c1、c2、c3`来创建`Foo`类的实例对象。
>
> ```java
> Foo foo = (Foo)c1.newInstance();//前提是必须有无参的构造方法。强制类型转换,可以用接口类型
> ```
#### 静态加载类
> 编译时加载类是静态加载
#### 动态加载类
> 运行时加载是动态加载。动态加载可以在运行时确定需要使用的类,而不用把所有类全部加载到类中。对于相似的类,可以为这些类实现一个接口。将该接口用于实例化类类型的强制转换。同时有新类时,只要该类实现该接口,原来的文件不必要重新编译
#### 基本数据类型对应类类型
```java
Class c1 = int.class;
Class c2 = String.class;
Class c3 = void.class;
```
#### Class类基本API
##### 获取方法信息
```java
Class c = obj.getClass();// obj是某个类的实例
String name = c.getName();// 获取类名称
Method[] ms = c.getMethods();// 所有public方法,包括继承来的
Method[] ms = c.getDeclaredMethods(); //该类自己声明的方法(包括private),不包括继承的
String name = ms[i].getName();// 获取方法名
Class returnType = ms[i].getReturnType();// 获取返回值类型的类类型(!注意是类类型)
Class[] paramTypes = ms[i].getParameterTypes();//获取参数列表的类型的类类型(!注意是类类型)
```
##### 获取成员变量信息
```java
Field[] fs = c.getFields();// 获取public以及继承来的成员变量
Field[] fs = c.getDeclaredFields();//获取自己声明的成员变量
Class type = Field[i].getType();// 获取成员变量的类类型
```
##### 获取构造函数信息
```java
// 构造函数也是对象,java.lang.reflect.Constructor
Constructor[] cs = c.getConstructor();// 获取所有public的构造函数
Constructor[] cs = c.getDeclaredConstructor();// 获取所有构造函数
```
### 方法的反射
> 方法可由方法的名称和方法的参数列表决定
```java
A a = new A();
Class c = a.getClass();
Method m = c.getMethod(name,int.Class,int.Class);// 方法名,可变参数列表
// 反射操作
Object o = m.invoke(a,10,30);// 实例对象,可变参数列表.无论方法是否有返回,invoke都会返回一个值。如果没有具体返回值,invoke返回nullc.
```
### 集合泛型的本质
```java
ArrayList list = new ArrayList();
ArrayList list1 = new ArrayList();
list1.add("hello");
//list1.add(20);// 编译失败
Class c1 = list.getClass();
Class c2 = list1.getClass();
```
`c1`等于`c2`吗?`c1==c2`结果返回`true`,说明编译之后集合的泛型是去泛型化的。Java中集合的泛型是防止错误输入的,只在编译阶段有效,绕过编译就无效了。通过方法的反射绕过编译。
```java
Method m = c2.getMethod("add",Object.class);
m.invoke(list1,20);// 绕过编译操作,编译成功
System.out.println(list1);// [hello,20]
/*不能这样遍历,类型错误
for(String str:list1){
System.out.println(str);
}
*/
```
一键复制
编辑
Web IDE
原始数据
按行查看
历史