https://jonblog.site/2024/05/28/designpattern-proxy/ https://jonblog.site/2024/06/06/annotation/
https://www.oracle.com/technical-resources/articles/java/javareflection.html https://www.bilibili.com/video/BV1tY411Z799
reflect demo 常用反射用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 class Person { private int age; private String name; public Person () { } public Person (int age, String name) { this .age = age; this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } public String getName () { return name; } public void setName (String name) { this .name = name; } } class SuperMan extends Person implements ActionInterface { private boolean BlueBriefs; public void fly () { System.out.println("超人会飞耶~~" ); } public boolean isBlueBriefs () { return BlueBriefs; } public void setBlueBriefs (boolean blueBriefs) { BlueBriefs = blueBriefs; } @Override public void walk (int m) { System.out.println("超人会走耶~~走了" + m + "米就走不动了!" ); } } interface ActionInterface { public void walk (int m) ; } public class ReflectMethod { public static void Demo1 () { Person person = new Person (); System.out.println("Demo1: 包名: " + person.getClass().getPackage().getName() + "," + "完整类名: " + person.getClass().getName()); } public static void Demo2 () throws ClassNotFoundException { Class<?> class1 = null ; Class<?> class2 = null ; class1 = Class.forName("reflection.Person" ); System.out.println("Demo2:(写法1) 包名: " + class1.getPackage().getName() + "," + "完整类名: " + class1.getName()); class2 = Person.class; System.out.println("Demo2:(写法2) 包名: " + class2.getPackage().getName() + "," + "完整类名: " + class2.getName()); } public static void Demo3 () throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class<?> class1 = null ; class1 = Class.forName("reflection.Person" ); Person person = (Person) class1.newInstance(); person.setAge(20 ); person.setName("LeeFeng" ); System.out.println("Demo3: " + person.getName() + " : " + person.getAge()); } public static void Demo4 () throws ClassNotFoundException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { Class<?> clazz = Person.class; Constructor<?>[] constructors = clazz.getConstructors(); for (Constructor<?> constructor : constructors) { System.out.println("Constructor: " + constructor); Class<?>[] parameterTypes = constructor.getParameterTypes(); for (Class<?> paramType : parameterTypes) { System.out.println("Parameter type: " + paramType.getName()); } Parameter[] parameters = constructor.getParameters(); for (Parameter parameter : parameters) { System.out.println("Parameter: " + parameter.getName() + ", Type: " + parameter.getType()); } System.out.println(); } try { final Class<?>[] stringParam = {String.class}; final Constructor<?> consString = Person.class.getConstructor(stringParam); Person personString = (Person) consString.newInstance(new Object []{99 }); System.out.println("stringParam " + personString); final Class<?>[] stringIntParam = {int .class, String.class}; final Constructor<?> consStringInt = Person.class.getConstructor(stringIntParam); Person person1 = (Person) consStringInt.newInstance(new Object []{99 , "john" }); System.out.println("stringIntParam " + person1); } catch (NoSuchMethodException e) { throw new RuntimeException (e); } Class<?> class1 = null ; Person person1 = null ; Person person2 = null ; class1 = Class.forName("reflection.Person" ); Constructor<?>[] constructors1 = class1.getConstructors(); person1 = (Person) constructors1[0 ].newInstance(); person1.setAge(30 ); person1.setName("leeFeng" ); person2 = (Person) constructors1[1 ].newInstance(20 , "leeFeng" ); System.out.println("Demo4: " + person1.getName() + " : " + person1.getAge() + " , " + person2.getName() + " : " + person2.getAge() ); public static void Demo5 () throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException, InstantiationException, ClassNotFoundException { Class<?> class1 = null ; class1 = Class.forName("reflection.Person" ); Object obj = class1.newInstance(); Field personNameField = class1.getDeclaredField("name" ); personNameField.setAccessible(true ); personNameField.set(obj, "胖虎先森" ); System.out.println("Demo5: 修改属性之后得到属性变量的值:" + personNameField.get(obj)); } public static void Demo6 () throws ClassNotFoundException { Class<?> class1 = null ; class1 = Class.forName("reflection.SuperMan" ); Class<?> superClass = class1.getSuperclass(); System.out.println("Demo6: SuperMan类的父类名: " + superClass.getName()); System.out.println("===============================================" ); Field[] fields = class1.getDeclaredFields(); for (int i = 0 ; i < fields.length; i++) { System.out.println("类中的成员: " + fields[i]); } System.out.println("===============================================" ); Method[] methods = class1.getDeclaredMethods(); for (int i = 0 ; i < methods.length; i++) { System.out.println("Demo6,取得SuperMan类的方法:" ); System.out.println("函数名:" + methods[i].getName()); System.out.println("函数返回类型:" + methods[i].getReturnType()); System.out.println("函数访问修饰符:" + Modifier.toString(methods[i].getModifiers())); System.out.println("函数代码写法: " + methods[i]); } System.out.println("===============================================" ); Class<?> interfaces[] = class1.getInterfaces(); for (int i = 0 ; i < interfaces.length; i++) { System.out.println("实现的接口类名: " + interfaces[i].getName()); } } public static void Demo7 () throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException { Class<?> class1 = null ; class1 = Class.forName("reflection.SuperMan" ); System.out.println("Demo7: \n调用无参方法fly():" ); Method method = class1.getMethod("fly" ); method.invoke(class1.newInstance()); System.out.println("调用有参方法walk(int m):" ); method = class1.getMethod("walk" , int .class); method.invoke(class1.newInstance(), 100 ); method.invoke(new SuperMan (), 666 ); } public static void Demo8 () throws ClassNotFoundException { Class<?> class1 = null ; class1 = Class.forName("reflection.SuperMan" ); String nameString = class1.getClassLoader().getClass().getName(); System.out.println("Demo8: 类加载器类名: " + nameString); } }
class 类是程序的一部分,每个类都有一个Class对象,每当编写并编译了一个新类就会产生一个Class对象(保存在一个同名的.class文件中)。为了生成这个对象就要用到JVM 分析主要的类和方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 interface HasBatteries {}interface Waterproof {}interface Shoots {}class Toy { Toy() { } Toy(int i) { } } class FancyToy extends Toy implements HasBatteries , Waterproof, Shoots { FancyToy() { super (1 ); } } public class ToyTest { static void printInfo (Class cc) { Print.print("Class name: " + cc.getName() + " is Interface ? [" + cc.isInterface() + "]" ); Print.print("Simple name: " + cc.getSimpleName()); Print.print("Canonical name : " + cc.getCanonicalName()); } public static void main (String[] args) { Class c = null ; try { c = Class.forName("TypeInfomation.Demo.FancyToy" ); } catch (ClassNotFoundException e) { Print.print("Can't find FancyToy" ); System.exit(1 ); } Print.print(c); printInfo(c); Print.print(); for (Class face : c.getInterfaces()) { printInfo(face); Print.print(); } Class up = c.getSuperclass(); Object obj = null ; try { obj = up.newInstance(); } catch (InstantiationException e) { Print.print("Cannot instantiate" ); System.exit(1 ); } catch (IllegalAccessException e) { Print.print("Cannot access" ); System.exit(1 ); } printInfo(obj.getClass()); } }
Class类 所有的Class对象都属于这个 类的一个static成员,Class对象和其他对象一样,我们可以使用 Class.forName("Gum")
获取并操作它的引用(这就是类加载器的工作), 从上面的代码可以看到,getSuperclass()方法查询其直接基类,这将返回用来进一步查询的Class对象。由此,可以在运行时发现一个对象完整的类继承结构
newInstance方法 Class的newInstance()实现“虚拟构造器”的一种途径,虚拟构造器寻你生命”我不知道你的确切类型,但是无论如何要正确地创建自己”,代码中的 up 只是一个Class引用,在编译期不具备任何更进一步的类型信息,创建新实例时,会得到指向Toy对象的Object引用,可以转型操作它。
动态代理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class DynamicProxyHandler implements InvocationHandler { private Object proxied; public DynamicProxyHandler (Object proxied) { this .proxied = proxied; } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { System.out.println("**** proxy: " + proxy.getClass() + ". method: " +method + ", args " + args); if (args !=null ) for (Object arg : args) System.out.println(" " + arg); return method.invoke(proxied,args); } } public class SimpleDynamicProxy { public static void consumer (Interface iface) { iface.doSomething(); iface.somethingElse("bonobo" ); } public static void main (String[] args) { RealObject real = new RealObject (); Interface proxy = (Interface) Proxy.newProxyInstance(Interface.class.getClassLoader(), new Class []{Interface.class},new DynamicProxyHandler (real)); consumer(proxy); } }
more demo about dynamic proxy in this article
https://jonblog.site/2024/05/28/designpattern-proxy/
2、javap 一个随JDK发布的反编译工具 命令行 到Cat.java所对应的Cat.class文件的位置 运行 javap -private Cat.class
可以反编译源程序
3、没有任何方式可以阻止反射到达并调用那些非公共访问权限的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class ModifyingPrivateFields { public static void main (String[] args) throws Exception { WithPrivateFinalField pf = new WithPrivateFinalField (); System.out.println(pf); Field f = pf.getClass().getDeclaredField("i" ); f.setAccessible(true ); System.out.println("f.getInt(pf): " + f.getInt(pf)); f.setInt(pf,47 ); System.out.println(pf); Print.print(); f =pf.getClass().getDeclaredField("s" ); f.setAccessible(true ); System.out.println("f.get(pf): " +f.get(pf)); f.set(pf,"you are totally safe" ); System.out.println(pf); Print.print(); f = pf.getClass().getDeclaredField("s2" ); f.setAccessible(true ); System.out.println("f.get(pf): " +f.get(pf)); f.set(pf,"No,you're not!" ); System.out.println(pf); } } class WithPrivateFinalField { private int i = 1 ; private final String s = " I'm totally safe" ; private String s2 = "Am I safe?" ; public String toString () { return "i = " + i + ", " + s + ", " + s2; } }
https://github.com/hengzhou/Rejection http://blog.csdn.net/ljphhj/article/details/12858767
this video write code simulate JDK dynamic proxy
https://www.bilibili.com/video/BV1Ve411o7WM
反射机制 Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java的反射机制。
基本使用 1 2 3 4 5 6 package reflection;public class MethodReflect { public int addResult (int addNum) { return addNum; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Class < ?>cls = Class.forName("reflection.MethodReflect" ); Object obj = cls.newInstance();Method addMethod = cls.getMethod("addResult" , new Class [] { int .class }); System.out.println("修饰符: " + Modifier.toString(addMethod.getModifiers())); System.out.println("返回值: " + addMethod.getReturnType()); System.out.println("方法名称: " + addMethod.getName()); System.out.println("参数列表: " + addMethod.getParameterTypes()); int result = (int ) addMethod.invoke(obj, 2 );System.out.println("调用addResult后的运行结果:" + result); System.out.println("--------------------------------" ); Method toStringMethod = cls.getMethod("toString" , new Class [] {});System.out.println("修饰符: " + Modifier.toString(toStringMethod.getModifiers())); System.out.println("返回值: " + toStringMethod.getReturnType()); System.out.println("方法名称: " + toStringMethod.getName()); System.out.println("参数列表: " + toStringMethod.getParameterTypes()); String msg = (String) toStringMethod.invoke(obj);System.out.println("调用toString后的运行结果:" + msg);
Method类的invoke(Object obj,Object args[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 public class InvokeTester { private String name; public void setName (String name) { this .name = name; } public String getName () { return name; } public InvokeTester () { } public int add (int param1, int param2) { return param1 + param2; } public String echo (String mesg) { return "echo" + mesg; } public static void main (String[] args) throws Exception { Class classType = InvokeTester.class; Object invokertester = classType.newInstance(); Method addMethod = classType.getMethod("add" , new Class []{ int .class, int .class }); Object result = addMethod.invoke(invokertester, new Object []{ new Integer (100 ), new Integer (200 ) }); System.out.println(result); Method echo = classType.getMethod("echo" , new Class []{ String.class }); Object obj = echo.invoke(invokertester, new Object []{ new String ("Jon is very good!!!" ) }); System.out.println(obj.toString()); InvokeTester test = new InvokeTester (); test.setName("黄翊" ); Method[] methods = test.getClass().getDeclaredMethods(); for (int i = 0 ; i < methods.length; i++) { if (methods[i].getName().indexOf("get" ) != -1 && methods[i].getName().indexOf("Name" ) != -1 ) { if (methods[i].invoke(test, null ) == null ) { System.out.println("此对象没有值!!!" ); } else { Object strName = methods[i].invoke(test, null ); System.out.println(strName); } } } } }
invoke方法的使用 实际上invoke方法的使用,和我们常见的有所区别。
我们经常创建一个对象A,A对象里面的方法getA()方法,然后A.getA()
我们采用新的方式调用 (1)弄一个方法的“替身”(其实就是构建一个Method对象,让这个Method对象来代替你现在要用的方法) (2)然后给替身需要的对象和参数,让替身去替你调用(像替身替你去战斗)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package reflection;import org.junit.jupiter.api.Test;import java.lang.reflect.Method;public class InvokeTest { public void test (String[] arg) { for (String string : arg) { System.out.println("zp is " + string); } } @Test public void invokeDemo () throws Exception { Class<InvokeTest> clazz = (Class<InvokeTest>) Class.forName("reflection.InvokeTest" ); InvokeTest m = new InvokeTest (); String[] s = new String []{"handsome" ,"smart" }; Method method = clazz.getMethod("test" , String[].class); method.invoke(m, (Object) s); } }
输出结果
zp is handsome zp is smart
所以使用invoke方法要比别的方法多做一步,就是构建一个Method对象,这个对象替代的是现在程序要调用方法的替代品。
而且除了参数以外,invoke还会多要一个对象,因为方法调用需要对象,所以invoke要想调用的目标方法,就需要目标方法的需要的对象。
看起来invoke方法不仅比平常方法直接调用要麻烦很多,但是你有想过吗,我只需要输入参数,我可以调用替代各种方法,在未知的情况下,根据条件决定去调用什么对象,什么方法,一下子就让代码变得灵活,这不仅是invoke的妙处,也是整个反射的妙处,在程序运行时根据条件灵活使用。
https://zhuanlan.zhihu.com/p/350058223
Method信息 我们已经能通过Class
实例获取所有Field
对象,同样的,可以通过Class
实例获取所有Method
信息。Class
类提供了以下几个方法来获取Method
:
Method getMethod(name, Class...)
:获取某个public
的Method
(包括父类)
Method getDeclaredMethod(name, Class...)
:获取当前类的某个Method
(不包括父类)
Method[] getMethods()
:获取所有public
的Method
(包括父类)
Method[] getDeclaredMethods()
:获取当前类的所有Method
(不包括父类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Student extends Person { public int getScore (String type) { return 99 ; } private int getGrade (int year) { return 1 ; } } class Person { public String getName () { return "Person" ; } public void hello () { System.out.println("Person:hello" ); } }
1 2 Class<Student> methodClass = Student.class; Arrays.stream(methodClass.getMethods()).forEach(method -> System.out.println("method方法: " + method));
打印出
method方法: public int reflection.liao.Student.getScore(java.lang.String) method方法: public void reflection.liao.Person.hello() method方法: public java.lang.String reflection.liao.Person.getName()
1 2 Class<Person> methodClass = Person.class; Arrays.stream(methodClass.getMethods()).forEach(method -> System.out.println("method方法: " + method));
打印出
method方法: public void reflection.liao.Person.hello() method方法: public java.lang.String reflection.liao.Person.getName()
…object方法
getMethods()可以 获取所有public
的Method
(包括父类),
不能获取到子类的方法,除非是是多肽实现
getDeclaredMethod获取的Method能否调用子类? 父类class通过getDeclaredMethod获取的Method能否调用子类的对象
验证是不可以
1 2 3 4 5 6 7 8 9 10 11 Class<?> clz = Class.forName("reflection.liao.Person" ); Object o = clz.newInstance();Method methodGetName = clz.getMethod("getName" );Object noParams = methodGetName.invoke(o);System.out.println(noParams); Method methodHello = clz.getMethod("hello" );System.out.println(methodHello.invoke(o)); Method methodGetGrade = clz.getMethod("getGrade" );System.out.println(methodGetGrade.invoke(o));
A Person Person:hello null // 这个null是哪里来的
提示
java.lang.NoSuchMethodException: reflection.liao.Person.getGrade()
所以是调用不了的。
https://www.liaoxuefeng.com/wiki/1252599548343744/1264803678201760
http://www.51gjie.com/java/796.html
https://www.cnblogs.com/onlywujun/p/3519037.html>