文章目录
一、JAVA反射是什么?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。
二、使用说明
1.获取Class对象的三种方式
1.1第一种方式
Object ——> getClass()
Blog blog = new Blog();
Class blogClass1 = blog.getClass();
System.out.println(blogClass1.getName());
1.2第二种方式
任何数据类型(包括基本数据类型)都有一个“静态”的class属性
Class<Blog> blogClass2 = Blog.class;
System.out.println(blogClass2 == blogClass1);
1.3第三种方式
通过Class类的静态方法:forName(String className)(常用)
Class blogClass3 = Class.forName("org.springblade.test.entity.Blog");
System.out.println(blogClass3 == blogClass2);
2.获取字段
2.1获取所有公有的字段
Field[] fieldArray = blogClass3.getFields();
for (Field f : fieldArray) {
System.out.println(f);
}
2.2获取所有的字段(包括私有、受保护、默认的)
fieldArray = blogClass3.getDeclaredFields();
for (Field f : fieldArray) {
System.out.println(f);
}
2.3获取公有字段**并调用
Field f = blogClass3.getField("blogTitle");
System.out.println(f);
//获取一个对象 //产生Blog对象--》Blog blog = new Blog();
Blog blog1 = blogClass2.getConstructor().newInstance();
//为字段设置值 //为Blog对象中的blogContent属性赋值--》blog.blogContent = "陈奕迅"
f.set(blog1, "陈奕迅");
//验证
System.out.println("验证姓名:" + blog1.getBlogTitle());
2.4获取私有字段**并调用
f = blogClass3.getDeclaredField("blogContent");
System.out.println(f);
//暴力反射,解除私有限定
f.setAccessible(true);
f.set(blog1, "张学友");
System.out.println("验证:" + blog1);
3.获取方法
3.1获取所有的公有方法
blogClass3.getMethods();
Method[] methodArray = blogClass3.getMethods();
for (Method m : methodArray) {
System.out.println(m);
}
3.2获取所有的方法,包括私有的
methodArray = blogClass3.getDeclaredMethods();
for (Method m : methodArray) {
System.out.println(m);
}
3.3获取公有的setBlogTitle()方法
Method m = blogClass2.getMethod("setBlogTitle", String.class);
System.out.println(m);
//实例化一个Blog对象
Object obj = blogClass2.getConstructor().newInstance();
m.invoke(obj, "获取公有的setBlogTitle()方法");
System.out.println(obj);
3.4获取私有的setBlogContent()方法
m = blogClass2.getDeclaredMethod("setBlogContent", String.class);
System.out.println(m);
//解除私有限定
m.setAccessible(true);
//需要两个参数,一个是要调用的对象(获取有反射),一个是实参
m.invoke(obj, "获取私有的setBlogContent()方法");
System.out.println("返回值:" + obj);
4.Java中泛型Class< T >、T与Class< ? >
4.1区别
单独的 T 代表一个类型 ,而 Class< T >代表这个类型所对应的类, Class< ? >表示类型不确定的类
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型
举例说明:
Set<T> 表示 集合里 是 T类的实例
List<E> 表示 集合里 是 E类的实例
List<?> 表示 集合里的对象类型不确定,未指定
List 同 List<?> 是一样的。
泛型的作用:
1、用泛型:
List<T> list = new ArrayList<T>();
T t = list.get(0);
2、不用泛型:
List list = new ArrayList();
T t = (T)list.get(0);
4.2如何创建一个Class< T >类型的实例
就像使用非泛型代码一样,有两种方式:调用方法 Class.forName() 或者使用类常量X.class。
Class.forName() 被定义为返回 Class<?>。
另一方面,类常量 X.class 被定义为具有类型 Class<X>。
所以 String.class 是Class<String> 类型的。
4.3方法中为什么需要< T > T修饰
泛型的声明,必须在方法的修饰符(public,static,final,abstract等)之后,返回值声明之前。
public static <T> T demo(HttpServletRequest request,Class<T> clazz){}
其中第一个是与传入的参数Class相对应的,相当于返回值的一个泛型,后面的T是返回值类型,代表方法必须返回T类型的(由传入的Class决定)