反射原理图
java Reflection
1.反射机制允许程序在执行期借助Reflection API取得任何类的内部消息(如成员变量、构造器、成员方法等等),并能才能操作对象的属性及方法。并且反射在设计模式和框架底层都会用到
2.加载完类之后,在堆中产生一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。
反射相关类
java反射机制可以完成如下:
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时得到任意一个类所具有的成员变量和方法
4.在运行时调用任意一个对象的成员变量和方法
5.生成动态代理
反射相关的主要类:
1.java.lang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象
2.java.lang.reflect.Method:代表类的方法,Method对象表示某个类的方法
3.java.lang.reflect.Filed:代表类的成员变量,Filed对象表示某个类的成员变量
4.java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示构造器
5.这些类都在java.lang.reflection
反射调用优化
反射优点和缺点:
1.优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑
2.缺点:使用反射基本是解释执行,对执行速度有影响
反射调用优化(关闭访问检查):
1.Method和Filed、Constructor对象都有setAccessible()方法
2.setAccessible作用是启动和禁用访问安全检查的开关
3.参数值为true表示,反射的对象在使用时取消访问检查,提高反射效率。参数值为false则表示反射的对象执行访问检查。
Class类
基本介绍:
1.Class也是类,它也继承Object类
2.Class类对象不是new出来的,而是系统创建的
3.对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
4.每个类的实例都会记得自己是由哪个Class实例所生成
5.通过Class可以完整地得到一个类的完整结构,通过一系列API
6.Class对象是存放在堆的
7.类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括:方法代码、变量名、方法名、访问权限等等)
Class类的常用方法:
package com.jh.class_;
//演示Class类的常用方法
import java.io.File;
import java.lang.reflect.Field;
public class Class02 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
String path = "com.jh.class_.Dog";
//1.获取Dog类,对应的Class对象
// <?> 表示不确定的java类型
// ClassNotFoundException :类不存在异常
Class<?> class01 = Class.forName(path);
//2.输出 class01class com.jh.class_.Dog
// 显示class01对象,是哪个类的Class对象
System.out.println(class01);//class com.jh.class_.Dog
// 输出class01的运行类型,
System.out.println(class01.getClasses());//java.lang.Class;@4554617c
//3.得到包名
System.out.println(class01.getPackage().getName());//com.jh.class_
//4.得到类名
System.out.println(class01.getName());//com.jh.class_.Dog
//5.通过class01 创建对象实例
Object o = class01.newInstance();
//Dog dog = (Dog)class01.newInstance();
System.out.println(o);//Dog{name='tom', id=10001, age=23}
//6.通过反射获取属性 name
Field name = class01.getField("name");
System.out.println(name.get(o));//tom
//7.通过反射给属性赋值
name.set(o,"jim");
System.out.println(name.get(o));//jim
//8.得到所以的属性
Field[] fields = class01.getFields();
for (Field f : fields){
System.out.println(f.getName());
}
/*name
id
age*/
}
}
获取Class对象六种方式
1.前提:已知一个类的全类名,且该类在类路径下,可以通过Class类的静态方法forName()获取,可以抛出ClassNotFoundException,实例:Class class01 = Class.forName("java.lang.Cat"); 应用场景:多用于配置文件,读取全路径,加载类
2.前提:若已知具体的类,通过类的class获取,该方式最为安全可靠,程序性能最高,实例:Class class01 = Cat.class;应用场景:多用于参数传递,例如通过反射得到对应构造器对象
3.前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象 ,实例:Class class01 = 对象.getClass();应用场景:通过创建好的对象,获取Class对象
4.其他方式:ClassLoader classloader = 对象.getClass().getClassLoader();Class class01 = classloader.loadClass("类的全类名")
5.基本数据(int,char,boolean,float,double,byte,long,short)按如下方式得到Class类对象
Class class = 基本数据类型.class;
6.基本数据类型对应的包装类,可以通过.type得到Class类对象
Class class = 包装类.TYPE;
package com.jh.class_;
//演示Class各种方式(6种)
public class GetClass_ {
public static void main(String[] args) throws ClassNotFoundException {
/*1.
* 已知一个类的全类名,且该类的类路径下,
* 可通过Class类的静态方法forName()获取,
* 可抛出ClassNotFoundException
* 多用于配置文件,读取类全路径,加载类
* */
String path = "com.jh.class_.Dog";//通过读取配置文件获取
Class<?> aClass = Class.forName(path);
System.out.println(aClass);//class com.jh.class_.Dog
/*2.
*若已知具体的类
* 通过类的class获取,
*该方法最为安全可靠,
* 多用于参数传递,如反射得到对应构造器对象
* */
Class class02 = Dog.class;
System.out.println(class02);//class com.jh.class_.Dog
/*3.
*已知某个类的实例,调用该实例的getClass()方法获取Class对象
*通过创建好的对象,获取Class对象
* */
Dog dog = new Dog();
Class<? extends Dog> aClass1 = dog.getClass();
System.out.println(aClass1);//class com.jh.class_.Dog
/*4.
* 通过类加载器来获取类的Class对象
* */
//第一步:先得到类加载器
ClassLoader classLoader = dog.getClass().getClassLoader();
//第二步:通过类加载器得到Class对象
Class<?> aClass2 = classLoader.loadClass(path);
System.out.println(aClass2);//class com.jh.class_.Dog
/*5.
* 基本数据类型,按如下方式得到Class类对象
* Class class = 基本数据类型.class
* */
Class<Integer> integerClass = int.class;
System.out.println(integerClass);//int
/*6.
*基本数据类型对应的包装类,可以通过.TYPE得到Class类对象
* Class class = 包装类.TYPE
* */
Class<Integer> type = Integer.TYPE;
System.out.println(type);//int
}
}
那些类型有Class对象
1.外部类、成员内部类、静态内部类、局部内部类、匿名内部类
2.interface:接口
3.数组
4.enum:枚举
5.annotation:注解
6.基本数据类型
7.void
packagecom.jh.class_;
//演示那些类型有class对象
importjava.io.Serializable;
publicclassAllTypeClass{
publicstaticvoidmain(String[]args){
//外部类
Class<String>class01=String.class;
System.out.println(class01);
//接口
Class<Serializable>class02=Serializable.class;
System.out.println(class02);
//数组
Class<Integer[]>class03=Integer[].class;
System.out.println(class03);
//二维数组
Class<float>class04=float.class;
System.out.println(class04);
//注解
Class<Deprecated>class05=Deprecated.class;
System.out.println(class05);
//枚举
Class<Thread.State>class06=Thread.State.class;
System.out.println(class06);
//基本数据类型
Class<Long>class07=long.class;
System.out.println(class07);
//void
Class<Void>class08=void.class;
System.out.println(class08);
//class
Class<Class>class09=Class.class;
System.out.println(class09);
}
}