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());
}
}
}
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 {
String path = "com.jh.class_.Dog";//通过读取配置文件获取
Class> aClass = Class.forName(path);
System.out.println(aClass);//class com.jh.class_.Dog
Class class02 = Dog.class;
System.out.println(class02);//class com.jh.class_.Dog
Dog dog = new Dog();
Class extends Dog> aClass1 = dog.getClass();
System.out.println(aClass1);//class com.jh.class_.Dog
//第一步:先得到类加载器
ClassLoader classLoader = dog.getClass().getClassLoader();
//第二步:通过类加载器得到Class对象
Class> aClass2 = classLoader.loadClass(path);
System.out.println(aClass2);//class com.jh.class_.Dog
Class
System.out.println(integerClass);//int
Class
System.out.println(type);//int
}
}
1.外部类、成员内部类、静态内部类、局部内部类、匿名内部类
2.interface:接口
3.数组
4.enum:枚举
5.annotation:注解
6.基本数据类型
7.void
packagecom.jh.class_;
//演示那些类型有class对象
importjava.io.Serializable;
publicclassAllTypeClass{
publicstaticvoidmain(String[]args){
//外部类
Class
System.out.println(class01);
//接口
Class
System.out.println(class02);
//数组
Class
System.out.println(class03);
//二维数组
Class
System.out.println(class04);
//注解
Class
System.out.println(class05);
//枚举
Class
System.out.println(class06);
//基本数据类型
Class
System.out.println(class07);
//void
Class
System.out.println(class08);
//class
Class
System.out.println(class09);
}
}