一、反射机制(reflect)
java是一门面向对象的编程语言
类 :从很多对象中抽取出来的共有的特征行为,抽象的描述,用来描述一组对象。
对象:在现实生活中,先存在好多对象,这些对象很多相同的特征(属性)和行为(方法)。
类是用来描述一组对象的,反射可以认为是用来描述一组类的,学习反射可以与java中的File的对比着学习。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
二、反射中的那些事
1、Class 用来描述类本身
2、Field 用来描述类中的属性
3、Method 用来描述类中的方法
4、Constructor 用来描述类中的构造方法
5、Package 用来描述类所在的包
6、Annotation 用来描述类中的注解如:@Override
关键:注解可以放置在类上面、属性上面、方法上面、构造方法上面、参数的前面。
三、怎样使用反射机制?
1、获取Class的三种方式:
1)Class clazz = Class.forName(“包名.类名”);这种方式存在异常,因为forName()中的参数是字符串,可能输入字符串字符串错误,系统给做了一个异常处理,需要抛出异常或者处理异常。
2)Class clazz = 类名.class;知道类的名字的时候直接用这个。
3)Class clazz = 对象.getClass();这个方法是Object中的方法,每个类中都有这个方法。
2、Class中的常用方法
1)int modifiers = getModifiers();获取类的修饰符,包括权限修饰符和特征修饰符。返回值是int类型的(这里不好理解)。
返回值表
返回值 | 所表示的修饰符 |
0 | 默认不写 |
1 | public |
2 | private |
4 | protected |
8 | static |
16 | final |
32 | synchronized |
64 | volatile |
128 | trainsient |
256 | native |
512 | interface |
1024 | abstract |
package TestReflect;
import java.util.ArrayList;
public class TestMain {
public static void main(String[] args) {
//通过Class对象操作Person.class类
//操作的是硬盘上的Person.class这个字节码文件,而不是Person.java源文件
try {
Class clazz = Class.forName("TestReflect.Person");
Class clacat =Cat.class;//Class clazz = 类名.class;知道类的名字的时候直接用这个。
/*
* 1)Class clazz = Class.forName("包名.类名");这种方式存在异常,
* 因为forName()中的参数是字符串,可能输入字符串字符串错误,系
* 统给做了一个异常处理,需要抛出异常或者处理异常。
*/
//此时的clazz就是Person这个类,有自己的结构:
/*
* 1、权限修饰符
* 2、特征修饰符
* 3、类名字
* 4、继承
* 5、实现
*/
int modifiers = clazz.getModifiers();
System.out.println("Person的修饰符是:"+modifiers);//Person的修饰符是public输出结果是1
//每一个修饰符用一个整数来表示
/*
* 从0开始----0 1 2 4 8 16 32 64 128 256 512 1024(成倍增长)
* 0---默认写 1---public 2---private 4---protected
* 8---static 16---final 32---synchronized 64---volatile
* 128---transient 256---native 512---interface
* 1024---abstract
*/
int modifierscat = clacat.getModifiers();
System.out.println("Cat的修饰符是:"+modifierscat);//Cat的修饰符是public abstract,结果是两个修饰符对应的整数之和
String name = clazz.getName();//获取类的名字,获取类的全名:包名+类名;
String simpleName = clazz.getSimpleName();//获取类的简单名:类名。
System.out.println("clazz的全名:"+name+"\nclazz的简单名:"+simpleName);
Package p = clazz.getPackage();//获取类所在的包,其中Package是抽取出来的一个类,获得的包p是Package类型;
//一般获取包名比较常用,所以Package下有个方法getName();通过包.getName()获取。
String pname = p.getName();
System.out.println("clazz所在的包名:"+pname);
Object obj = clazz.getSuperclass();//获取当前类的父类。注意:基类Object是所有类的父类。
String sname = obj.getClass().getSimpleName();//获取父类的简单名字,当然可以让clazz继承一个类来玩耍
System.out.println("clazz的父类是:"+sname);
System.out.println("----------------反射的一个简单应用------------------");
//查询ArrayList家族的继承关系
System.out.println("ArrayList的继承关系:");
//1、获取集合对应的那个类class
Class claarr = ArrayList.class;
//2、获取集合类的父类
Class claarrs = claarr.getSuperclass();
while(claarrs != null) {
System.out.println(claarrs.getName());
claarrs = claarrs.getSuperclass();
}
System.out.println("ArrayList实现的接口:");
//获取当前类的父亲的所有接口,既然是一堆接口,返回值是一个Class数组。
Class[] classes = claarr.getInterfaces();
for(Class c: classes) {
System.out.println(c);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2)String name = 类.getName();获取类的名字,获取类的全名:包名+类名;String simpleName = 类.getSimpleName();获取类的简单名:类名。
3)Package p = 类.getPackage();获取类所在的包,其中Package是抽取出来的一个类,获得的包p是Package类型;一般获取包名比较常用,所以Package下有个方法getName();通过包.getName()获取。
4)Object obj = 类.getSuperClass();获取当前类的父类。注意:基类Object是所有类的父类。
5)Class[] classes = 类.getInterfaces();//获取当前类的父亲的所有接口,既然是一堆接口,返回值是一个Class数组。
7)Object obj = 类.newInstance();相当于调用类中的无参数构造方法创建对象,为了保证返回值的类型一致,该方法的返回值是Object类型,在使用的时候注意造型。
//例如:构建一个Person类,通过操作Person这个类来创建对象:
Class clazz = Person.class;Person p = (Person)clazz.newInstance();clazz.newInstance();
//获得是一个Object对象,需要造型。
8)Field field = 类.getField();通过类来获取类中的属性,返回类型是一个Field类型
————写于2020年11月09日,后续持续更新,希望码友们一起探讨学习