发表时间:2022-03-25来源:网络
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。
通常的方式:引入需要的“包类”名称---->通过“new”实例化---->获得实例化对象
反射的方式:实例化对象---->getClass()方法---->得到完整的“包类”名称
框架 = 注解 + 反射 + 设计模式
只有当程序运行时我们才能知道调用的类
@Test public void test2(){ for(int i = 0;i < 100;i++){ int num = new Random().nextInt(3);//0,1,2 String classPath = ""; switch(num){ case 0: classPath = "java.util.Date"; break; case 1: classPath = "java.lang.Object"; break; case 2: classPath = "com.atguigu.java.Person"; break; } try { Object obj = getInstance(classPath); System.out.println(obj); } catch (Exception e) { e.printStackTrace(); } } } /* 创建一个指定类的对象。 classPath:指定类的全类名 */ public Object getInstance(String classPath) throws Exception { Class clazz = Class.forName(classPath); return clazz.newInstance(); }在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时获取泛型信息
在运行时调用任意一个对象的成员变量和方法
在运行时处理注解
生成动态代理
代码示例
@Test public void test1() throws Exception { Class clazz = Person.class; //1.通过反射,创建Person类对象 Constructor cons = clazz.getConstructor(String.class, int.class); Person person = cons.newInstance("Tom", 12); System.out.println(person);//Person{name='Tom', age=12} //2.通过反射,调用对象指定的属性、方法 //调用属性 Field age = clazz.getDeclaredField("age"); age.setAccessible(true); age.set(person, 10); System.out.println(person.toString());//Person{name='Tom', age=10} //调用方法 Method show = clazz.getDeclaredMethod("show"); show.invoke(person);//my name is Tom and age is 10 System.out.println("==================================="); //通过反射,可以调用Person类的私有结构的。比如:私有的构造器、方法、属性 //调用私有的构造器 Constructor cons1 = clazz.getDeclaredConstructor(String.class); cons1.setAccessible(true); Person p1 = cons1.newInstance("Bruce"); System.out.println(p1);//Person{name='Bruce', age=0} //调用私有的属性 Field name = clazz.getDeclaredField("name"); name.setAccessible(true); name.set(p1, "Jarry"); System.out.println(p1); //调用私有的方法 Method nation = clazz.getDeclaredMethod("nation", String.class); nation.setAccessible(true); Object nation1 = (String) nation.invoke(p1, "China");//相当于String nation = p1.showNation("China") System.out.println(nation1);//I come from China }在Object类中定义了以下的方法,此方法将被所有子类继承:
public final Class getClass()
以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即可以通过对象反射求出类的名称。
对象使用反射后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个结构( class/interface/enum/annotation/primitive type/void/[])的有关信息。 Class本身也是一个类 Class对象只能由系统建立对象 一个加载的类在JVM中只会有一个Class实例 一个Class对象对应的是一个加载到JVM中的一个.class文件 每个类的实例都会记得自己是由哪个Class实例所生成 通过Class可以完整地得到一个类中的所有被加载的结构 Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象类的加载过程:
程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)。接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此运行时类,就作为Class的一个实例。 换句话说,Class的实例就对应着一个运行时类。 加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式来获取此运行时类。
代码示例:
//创建Class的实例 String str = "test1.Person"; Class clazz = Class.forName(str); //调用Class的空参构造器创建对象 Object obj = clazz.newInstance; //获取clazz的name属性 Field field = clazz.getField("name"); field.set(obj,"Jarry"); Object name = filed.get(obj); System.out.println(name); //test1.Person为test1包下的Person类已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高
实例:Class clazz = String.class;
已知某个类的实例,调用该实例的getClass()方法获取Class对象
实例:Class clazz = person.getclass();
已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取, 可能抛出 ClassNotFoundException(比较常用)
实例:Class clazz = Class.forName(String classPath)
通过类加载器
实例:ClassLoader cl = this.getclass().getClassLoader(); Class clazz = cl.loadClass("类的全类名");
代码示例
@Test public void test2() throws ClassNotFoundException { //方式一:调用运行时类的属性:.class Class clazz1 = Person.class; System.out.println(clazz1);//class cn.bruce.java.Person //方式二:通过运行时类的对象,调用getClass() Person p1 = new Person(); Class clazz3 = Class.forName("cn.bruce.java.Person"); System.out.println(clazz3);//class cn.bruce.java.Person System.out.println(clazz1 == clazz2);//true System.out.println(clazz1 == clazz3);//true //方式四:使用类的加载器:ClassLoader (了解) ClassLoader classLoader = ReflectionTest.class.getClassLoader(); Class clazz4 = classLoader.loadClass("cn.bruce.java.Person"); System.out.println(clazz4);//class cn.bruce.java.Person System.out.println(clazz1 == clazz4);//true }方式一:new + 构造器
方式二:要创建Xxx类的对象,可以考虑:Xxx、Xxxs、XxxFactory、XxxBuilder类中查看是否有静态方法的存在。可以调用其静态方法,创建Xxx对象。
方式三:通过反射
class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
interface:接口
[]:数组
enum:枚举
annotation:注解@interface
primitive type:基本数据类型
void
在Java中万事万物皆对象
代码示例
@Test public void test3(){ Class c1 = Object.class; Class c2 = Comparable.class; Class c3 = String[].class; Class c4 = int[][].class; Class c5 = ElementType.class; Class c6 = Override.class; Class c7 = int.class; Class c8 = void.class; Class c9 = Class.class; int[] i1 = new int[10]; int[] i2 = new int[100]; Class[] getInterfaces() 确定此对象所表示的类或接口实现的接口。2.所继承的父类: public Class getParameterTypes();
4.全部的方法:
public Method[] getDeclaredMethods():返回此Class对象所表示的类或接口的全部方法
public Method[] getMethods():返回此Class对象所表示的类或接口的public的方法
Method类中:
5.全部的Field:
public Field[] getFields():返回此Class对象所表示的类或接口的public的Field。
public Field[] getDeclaredFields():返回此Class对象所表示的类或接口的全部Field
Field方法中:
6.Annotation相关
get Annotation(Class annotationClass)
getDeclaredAnnotations()
7.泛型相关
获取父类泛型类型:Type getGenericSuperclass()
泛型类型:ParameterizedType
获取实际的泛型类型参数数组:getActualTypeArguments()
8.类所在的包 Package getPackage()
getMethod():返回某个类的所有公用(public)方法包括其继承类的公用方法,当然也包括它所实现接口的方法 getDeclaredMethod():对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。当然也包括它所实现接口的方法 setAccessible(true):保证当前方法是可访问的,对于私有方法,需要设置当前方法可访问,否则默认不可访问获取属性Fieled
public class FiledTest { @Test public void test1() { Class clazz = Person.class; //获取属性结构 //getFields():获取当前运行时类及其父类中声明为public访问权限的属性 Field[] fields = clazz.getFields(); for (Field f : fields) { System.out.println(f); } System.out.println(); //getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性) Field[] declaredFields = clazz.getDeclaredFields(); for (Field f : declaredFields) { System.out.println(f); } } //权限修饰符 数据类型 变量名 @Test public void test2() throws ClassNotFoundException { Class clazz = Class.forName("cn.bruce.java1.Person"); Field[] declaredFields = clazz.getDeclaredFields(); for (Field f : declaredFields) { //1.权限修饰符 int modifiers = f.getModifiers(); System.out.print(Modifier.toString(modifiers)+"\t"); //2.数据类型 Class type = f.getType(); System.out.print(type.getName()+"\t"); //3.变量名 String fName = f.getName(); System.out.print(fName); System.out.println(); } } }获取方法Method
public class MethodTest { @Test public void test1() { Class clazz = Person.class; //getMethods():获取当前运行时类及其所有父类中声明为public权限的方法 Method[] methods = clazz.getMethods(); for (Method m : methods) { System.out.println(m); } System.out.println("============"); //getDeclaredMethods():获取当前运行时类中声明的所有方法。(不包含父类中声明的方法) Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method m : declaredMethods) { System.out.println(m); } } /* @Xxxx 权限修饰符 返回值类型 方法名(参数类型1 形参名1,...) throws XxxException{} */ @Test public void test2() throws ClassNotFoundException { Class clazz = Class.forName("cn.bruce.java1.Person"); Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method m : declaredMethods) { //1.获取方法声明的注解 Annotation[] annos = m.getAnnotations(); for (Annotation a : annos) { System.out.println(a); } //2.权限修饰符 System.out.print(Modifier.toString(m.getModifiers())+"\t"); //3.返回值类型 System.out.print(m.getReturnType().getName() + "\t"); //4.方法名 System.out.print(m.getName()); System.out.print("("); //5.形参列表 Class[] parameterTypes = m.getParameterTypes(); if (!(parameterTypes == null && parameterTypes.length == 0)) { for (int i = 0; i < parameterTypes.length; i++) { if (i == parameterTypes.length - 1) { System.out.print(parameterTypes[i].getName() + " args_" + i); break; } System.out.print(parameterTypes[i].getName() + "args_" + i + ","); } } System.out.print(")"); //6.抛出的异常 Class[] exceptionTypes = m.getExceptionTypes(); if (exceptionTypes.length > 0){ System.out.print("throws "); for (int i = 0; i < exceptionTypes.length; i++) { if (i==exceptionTypes.length -1){ System.out.print(exceptionTypes[i].getName()); break; } System.out.print(exceptionTypes[i].getName()+","); } System.out.println(); } } } }获取其他结构
public class OtherTest { /* 获取构造器结构 */ @Test public void test1() { Class clazz = Person.class; //getConstructors():获取当前运行时类中声明为public的构造器 Constructor[] constructors = clazz.getConstructors(); for (Constructor c : constructors) { System.out.println(c); } System.out.println("================"); //getDeclaredConstructors():获取当前运行时类中声明的所有的构造器 Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); for (Constructor c : declaredConstructors) { System.out.println(c); } } /* 获取运行时类的父类 */ @Test public void test2(){ Class clazz = Person.class; Class...interface) 创建一个动态代理类所对应的Class对象static Object newProxyInstance(ClassLoader loader, Class...interface, InvocationHandler h) 直接创建一个动态代理对象
创建一个实现接口 InvocationHandler的类,它必须实现invoke()方法,以完成代理的具体操作。
创建被代理类以及接口
通过Proxy的静态方法newProxyInstance(ClassLoader loader, Class...interface, InvocationHandler h)创建一个接口代理
通过代理类的实例调用被代理类的方法
使用 Proxy生成一个动态代理时,往往并不会凭空产生一个动态代理,这样没有太大的意义。通常都是为指定的目标对象生成动态代理。
这种动态代理在AOP中被称为AOP代理,AOP代理可代替目标对象,AOP代理包含了目标对象的全部方法。但AOP代理中的方法与目标对象的方法存在差异:
AOP代理里的方法可以在执行目标方法之前、之后插入一些通用处理

代码示例
//公共接口 interface Dog { void info(); void run(); } //被代理类 class HuntingDog implements Dog { @Override public void info() { System.out.println("我是一只猎狗"); } @Override public void run() { System.out.println("我跑的很快"); } } //通用方法 class DogUtils { public void method1() { System.out.println("=======通用方法一======="); } public void method2() { System.out.println("=======通用方法二======="); } } //动态代理实现 class MyInvocationHandler1 implements InvocationHandler { //需要被代理的对象 private Object target; public void SetTarget(Object target) { this.target = target; } //当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法:invoke() //将被代理类要执行的方法a的功能就声明在invoke()中 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { DogUtils dogUtils = new DogUtils(); //执行DogUtils对象中的method1 dogUtils.method1(); //通过obj对象来调用执行method方法 Object result = method.invoke(target, args); //执行DogUtils对象中的method2 dogUtils.method2(); return result; } } //动态代理类 class MyProxyFactory1 { //为target生成动态代理对象 public static Object getProxy(Object target) { //创建一个MyInvocationHandler对象 MyInvocationHandler1 handler = new MyInvocationHandler1(); //为MyInvocationHandler设置target对象 handler.SetTarget(target); //创建返回一个动态代理对象 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler); } } public class AOPTest { public static void main(String[] args) { Dog target = new HuntingDog(); Dog dog = (Dog) MyProxyFactory1.getProxy(target); dog.info(); dog.run(); } }我认为反射应该是指通过对象或者名字来找到对应的类
反射是通过得到.class字节码文件 操作.java类中的内容
在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。
类中有一个静态属性(类属性) 叫class,是一个Class类的实例
Class是类的类
类加载到内存中,类本身就作为Class的一个实例
根据Class.forName() 获取Class的一个实例,即 .class文件 运行时类,加载类
通过反射是可以获取到方法或者类的注解的 通过读取注解中的内容 根据不同的内容 我们可以让方法执行不同功能
比如注解内容为0 代表我们输出0
代理模式就是通过获得被代理类所实现的接口 然后创建代理对象也实现那个接口就完了
框架其实就是注解 加上反射 加上设计模式 三者构成框架
上一篇:Java程序执行流程三
皓盘云建最新版下载v9.0 安卓版
53.38MB |商务办公
ris云客移动销售系统最新版下载v1.1.25 安卓手机版
42.71M |商务办公
粤语翻译帮app下载v1.1.1 安卓版
60.01MB |生活服务
人生笔记app官方版下载v1.19.4 安卓版
125.88MB |系统工具
萝卜笔记app下载v1.1.6 安卓版
46.29MB |生活服务
贯联商户端app下载v6.1.8 安卓版
12.54MB |商务办公
jotmo笔记app下载v2.30.0 安卓版
50.06MB |系统工具
鑫钜出行共享汽车app下载v1.5.2
44.7M |生活服务