-
动静态语言(了解)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Est7l1PE-1638439101772)(D:MarkDown学习imgsreflect1.png)]
-
反射:将静态语言转换为动态语言机制
代码案例:
function f() { //静态字符串 var x = "var a=3,var b=5,alert(a+b)"; eval(x); }
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YYEl0767-1638439101775)(D:MarkDown学习imgsreflect2.png)]
1>反射机制研究及应用[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NoCzWKb5-1638439101776)(D:MarkDown学习imgsreflect3.png)]
2>反射的优缺点[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-57sm3gXu-1638439101778)(D:MarkDown学习imgsreflect4.png)]
3>反射相关的主要API[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jmeaXev0-1638439101786)(D:MarkDown学习imgsreflect5.png)]
二、理解Class类并获取Class实例 1>Class类[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-62e2pkdw-1638439101789)(D:MarkDown学习imgsreflect6-1638282179013.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ExPkVAe0-1638439101791)(D:MarkDown学习imgsreflect7-1638282184763.png)]
-
代码案例:
package com.cn.reflect; //什么叫反射 public class Test extends Object{ public static void main(String[] args) throws ClassNotFoundException { //通过反射获取类class的对象 Class c1 = Class.forName("com.cn.reflect.User"); System.out.println(c1); //class com.cn.reflect.User Class c2 = Class.forName("com.cn.reflect.User"); Class c3 = Class.forName("com.cn.reflect.User"); Class c4 = Class.forName("com.cn.reflect.User"); //一个类在内存中只有一个Class对象 //一个类被加载后,类的整个结构都会被封装在Class对象中 System.out.println(c2.hashCode()); //1163157884 System.out.println(c3.hashCode()); //1163157884 System.out.println(c4.hashCode()); //1163157884 } } //实体类:pojo entity class User{ private String name; private int id; private int age; public User() { } public User(String name, int id, int age) { this.name = name; this.id = id; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + ''' + ", id=" + id + ", age=" + age + '}'; } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MgFrUPe3-1638439101797)(D:MarkDown学习imgsreflect8-1638282189865.png)]
3>获取Class类的实例[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6IYiinzK-1638439101799)(D:MarkDown学习imgsreflect9.png)]
-
代码案例:
package com.cn.reflect; //测试Class类的创建方式 public class Test01 { public static void main(String[] args) throws ClassNotFoundException { //多态 Person person = new Student(); //这个人是学生 System.out.println("这个人是"+person.name); //方式一:通过对象获得 Class c1 = person.getClass(); //1163157884 System.out.println(c1.hashCode()); //方式二:通过forName获得 Class c2 = Class.forName("com.cn.reflect.Student"); //1163157884 System.out.println(c2.hashCode()); //方式三:通过类名.Class获得 Class
c3 = Student.class; //1163157884 System.out.println(c3.hashCode()); //方式四:基本内置类的包装类都有一个Type属性 Class c4 = Integer.TYPE; System.out.println(c4); //int //获得父类类型 Class c5 = c1.getSuperclass(); System.out.println(c5); //class com.cn.reflect.Person } } class Person{ public String name; public Person() { } public Person(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + ''' + '}'; } } //学生类 class Student extends Person{ public Student() { this.name="学生"; } } //老师类 class Teacher extends Person{ public Teacher() { this.name="老师"; } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GtxrncOs-1638439101802)(D:MarkDown学习imgsreflect10.png)]
-
代码案例:
package com.cn.reflect; import java.lang.annotation.ElementType; //所有类型的Class public class Test02 { public static void main(String[] args) { //类 Class c1 = Object.class; //接口 Class c2 = Comparable.class; //一维数组 Class c3 = String[].class; //二维数组 Class c4 = int[][].class; //注解 Class c5 = Override.class; //枚举 Class c6 = ElementType.class; //基本数据类型 Class c7 = Integer.class; //void Class c8 = void.class; //Class类 Class c9 = Class.class; System.out.println(c1); //class java.lang.Object System.out.println(c2); //interface java.lang.Comparable System.out.println(c3); //class [Ljava.lang.String; System.out.println(c4); //class [[I System.out.println(c5); //interface java.lang.Override System.out.println(c6); //class java.lang.annotation.ElementType System.out.println(c7); //class java.lang.Integer System.out.println(c8); //void System.out.println(c9); //class java.lang.Class //两个数组的长度不同,类型相同,hashCode值是相同的 //只要元素类型与维度一样,就是同一个Class int[] a = new int[10]; int[] b = new int[100]; //1163157884 System.out.println(a.getClass().hashCode()); //1163157884 System.out.println(b.getClass().hashCode()); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bXx20XY7-1638439101804)(D:MarkDown学习imgsreflect11.png)]
三、类的加载与CalssLoader 1>类加载的过程[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0gv9vneo-1638439101805)(D:MarkDown学习imgsreflect12.png)]
2>类的加载与CalssLoader的理解[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tx4dP0Au-1638439101807)(D:MarkDown学习imgsreflect13.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lgzu87fX-1638439101808)(D:MarkDown学习imgsreflect14.png)]
-
代码案例:
package com.cn.reflect; //类的加载 public class Test05 { public static void main(String[] args) { A a = new A(); System.out.println(A.m); } } class A{ //静态代码块 static { System.out.println("A类静态代码块的初始化"); m = 300; } static int m = 100; public A() { System.out.println("A类的无参构造初始化"); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z7bL7HIP-1638439101809)(D:MarkDown学习imgsreflect15.png)]
-
代码案例:
package com.cn.reflect; //测试类什么时候初始化 public class Test03 { static { System.out.println("Main类被加载"); } public static void main(String[] args) throws ClassNotFoundException { //1.主动引用 //Son son = new Son(); //2.反射也会产生主动引用 //Class.forName("com.cn.reflect.Son"); //3.不会产生类的引用的方法 //System.out.println(Son.b); //4.数组定义类引用 //Son[] array = new Son[5]; //Main类被加载 //5.引用常量 System.out.println(Son.M); //Main类被加载 1 } } class Father{ static int b = 2; static { System.out.println("父类被加载"); } } class Son extends Father{ static { System.out.println("子类被加载"); m = 300; } static int m = 100; static final int M = 1; }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hC90sHw2-1638439101810)(D:MarkDown学习imgsreflect16.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZucYzHSw-1638439101811)(D:MarkDown学习imgsreflect17.png)]
-
代码案例:
package com.cn.reflect; //系统类加载器 public class Test04 { public static void main(String[] args) throws ClassNotFoundException { //获取系统类的加载器![在这里插入图片描述](https://img-blog.csdnimg.cn/dfc2bdd2d25c4f9a8086542d2669b588.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASVRf5ZCR5bem5L2_,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center) ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); //sun.misc.Launcher$AppClassLoader@18b4aac2 System.out.println(systemClassLoader); //获取系统类加载器的父类加载器-->扩展类加载器 ClassLoader parent = systemClassLoader.getParent(); //sun.misc.Launcher$ExtClassLoader@4554617c System.out.println(parent); //获取扩展类加载器的父类加载器-->根加载器(c/c++) ClassLoader parent1 = parent.getParent(); System.out.println(parent1); //null //测试当前类是哪个类加载器加载的 ClassLoader classLoader =Class.forName("com.cn.reflect.Test04").getClassLoader(); //sun.misc.Launcher$AppClassLoader@18b4aac2 System.out.println(classLoader); //测试JDK内置类是哪个类加载器加载的 ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader(); System.out.println(classLoader1); //null //如何获取系统类加载器可以加载的路径 String property = System.getProperty("java.class.path"); System.out.println(property); } }
-
什么事双亲委派机制
当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归这个 *** 作,如果上级的类加载器没有加载,自己才会去加载这个类
-
双亲委派机制的作用
1、防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。 2、保证核心.class不能被篡改。通过委托方式,不会去篡改核心.class,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。
-
源码分析
protected Class> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // 首先检查这个classsh是否已经加载过了 Class> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { // c==null表示没有加载,如果有父类的加载器则让父类加载器加载 if (parent != null) { c = parent.loadClass(name, false); } else { //如果父类的加载器为空 则说明递归到bootStrapClassloader了 //bootStrapClassloader比较特殊无法通过get获取 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) {} if (c == null) { //如果bootstrapClassLoader 仍然没有加载过,则递归回来,尝试自己去加载class long t1 = System.nanoTime(); c = findClass(name); sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
委派机制的流程图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3d37jaU-1638439101812)(D:MarkDown学习imgsreflect18.png)]
当一个Hello.class这样的文件要被加载时。不考虑我们自定义类加载器,首先会在AppClassLoader中检查是否加载过,如果有那就无需再加载了。如果没有,那么会拿到父加载器,然后调用父加载器的loadClass方法。父类中同理也会先检查自己是否已经加载过,如果没有再往上。注意这个类似递归的过程,直到到达Bootstrap classLoader之前,都是在检查是否加载过,并不会选择自己去加载。直到BootstrapClassLoader,已经没有父加载器了,这时候开始考虑自己是否能加载了,如果自己无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException。
- 为什么要设计这种机制
这种设计有个好处是,如果有人想替换系统级别的类:String.java。篡改它的实现,在这种机制下这些系统的类已经被Bootstrap classLoader加载过了(为什么?因为当一个类需要加载的时候,最先去尝试加载的就是BootstrapClassLoader),所以其他类加载器并没有机会再去加载,从一定程度上防止了危险代码的植入。
总结
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q1xIZMmU-1638439101813)(D:MarkDown学习imgsreflect19.png)]
四、获取运行时类的对象 1>获取类的运行时结构[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MVzdbKnD-1638439101814)(D:MarkDown学习imgsreflect20.png)]
-
代码案例:
package com.cn.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; //获取类的信息 public class Test06 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { Class c1 = Class.forName("com.cn.reflect.User"); //获得类的名字 String name = c1.getName(); System.out.println(name); //com.cn.reflect.User String simpleName = c1.getSimpleName(); System.out.println(simpleName); //User System.out.println("====================="); //获得类的属性 Field[] fields = c1.getFields(); //只能找到public属性 fields = c1.getDeclaredFields(); //找到全部属性 for (Field field : fields) { System.out.println(field); } System.out.println("====================="); //获得指定属性的值 Field names = c1.getDeclaredField("name"); //private java.lang.String com.cn.reflect.User.name System.out.println(names); //获得类的方法 Method[] methods = c1.getMethods(); //获得本类及父类全部的public方法 for (Method method : methods) { System.out.println("正常的"+method); } methods = c1.getDeclaredMethods(); //获得本类的所有方法 for (Method method : methods) { System.out.println("DeclaredMethods"+method); } System.out.println("====================="); //获得指定方法 Method getName = c1.getMethod("getName", null); Method setName = c1.getMethod("setName", String.class); //public java.lang.String com.cn.reflect.User.getName() System.out.println(getName); //public void com.cn.reflect.User.setName(java.lang.String) System.out.println(setName); System.out.println("====================="); //获得指定的构造器 //获得本类及父类全部的构造方法 Constructor[] constructors = c1.getConstructors(); for (Constructor constructor : constructors) { //public com.cn.reflect.User() //public com.cn.reflect.User(java.lang.String,int,int) System.out.println(constructor); } //获得本类中所有的构造方法 Constructor[] declaredConstructors = c1.getDeclaredConstructors(); for (Constructor declaredConstructor : declaredConstructors) { //public com.cn.reflect.User() //public com.cn.reflect.User(java.lang.String,int,int) System.out.println(declaredConstructor); } //获得指定的构造器 Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class); //指定:public com.cn.reflect.User(java.lang.String,int,int) System.out.println("指定:"+declaredConstructor); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8JMU7HLY-1638439101815)(D:MarkDown学习imgsreflect21.png)]
3>调用方法[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mx0M0Bm5-1638439101816)(D:MarkDown学习imgsreflect22.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-upWnKqJo-1638439101816)(D:MarkDown学习imgsreflect23.png)]
4>setAccessible()[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7WbPc6tN-1638439101817)(D:MarkDown学习imgsreflect24.png)]
-
代码案例:
package com.cn.reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; //通过反射动态创建对象 public class Test07 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { //获得Class对象 Class c1 = Class.forName("com.cn.reflect.User"); //构造一个对象 User user = (User) c1.newInstance(); //本质是调用无参构造器 //User{name='null', id=0, age=0} System.out.println(user); System.out.println("============================="); //通过构造器创建对象 Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class); User user1 = (User) constructor.newInstance("张三", 1001, 22); //User{name='张三', id=1001, age=22} System.out.println(user1); System.out.println("============================="); //通过反射调用普通方法 User user2 = (User) c1.newInstance(); //通过反射获取一个方法 Method setName = c1.getDeclaredMethod("setName", String.class); //invoke:激活 (对象,“方法的值”) setName.invoke(user2,"李四"); //李四 System.out.println(user2.getName()); //通过反射 *** 作属性的值 User user3 = (User) c1.newInstance(); //获得指定的属性 Field name = c1.getDeclaredField("name"); //不能直接 *** 作私有属性,需关闭程序的安全检测,属性或方法的setAccessible(true) name.setAccessible(true); name.set(user3,"王五"); //王五 System.out.println(user3.getName()); } }
-
代码案例:
package com.cn.reflect; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; //分析性能问题 public class Test08 { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { test01(); //普通方式执行10万次需要:3ms test02(); //反射方式执行10万次需要:33ms test03(); //反射方式关闭检测执行10万次需要:5ms } //普通方式调用 public static void test01(){ User user = new User(); //测试程序执行的时长 //开始时间 long startTime = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { user.getName(); } //结束时间 long endtTime = System.currentTimeMillis(); //输出 System.out.println("普通方式执行10万次需要:"+(endtTime-startTime)+"ms"); } //反射方式调用 public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); //获取方法 Method getName = c1.getDeclaredMethod("getName", null); //测试程序执行的时长 //开始时间 long startTime = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { getName.invoke(user,null); } //结束时间 long endtTime = System.currentTimeMillis(); //输出 System.out.println("反射方式执行10万次需要:"+(endtTime-startTime)+"ms"); } //反射方式调用,关闭检测 public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); //获取方法 Method getName = c1.getDeclaredMethod("getName", null); //设置权限 getName.setAccessible(true); //测试程序执行的时长 //开始时间 long startTime = System.currentTimeMillis(); for (int i = 0; i < 100000; i++) { getName.invoke(user,null); } //结束时间 long endtTime = System.currentTimeMillis(); //输出 System.out.println("反射方式关闭检测执行10万次需要:"+(endtTime-startTime)+"ms"); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1PCnjBH3-1638439101818)(D:MarkDown学习imgsreflect25.png)]
-
代码案例:
package com.cn.reflect; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; //通过反射获取泛型 public class Test09 { //作为参数类型 public void test01(Map
map, List list){ System.out.println("test01"); } //作为返回值类型 public Map test02(){ System.out.println("test02"); return null; } public static void main(String[] args) throws NoSuchMethodException { //通过反射获取方法 Method method = Test09.class.getMethod("test01", Map.class, List.class); //获取参数类型 Type[] genericParameterTypes = method.getGenericParameterTypes(); //遍历泛型的参数类型 for (Type genericParameterType : genericParameterTypes) { //***:java.util.Map //***:java.util.List System.out.println("***:"+genericParameterType); //判断泛型的参数类型是否属于参数化类型 if (genericParameterType instanceof ParameterizedType){ //获得真实类型 Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); //遍历真实类型 for (Type actualTypeArgument : actualTypeArguments) { //***:java.util.Map //真实类型信息:class java.lang.String //真实类型信息:class com.cn.reflect.User //***:java.util.List //真实类型信息:class com.cn.reflect.User System.out.println("真实类型信息:"+actualTypeArgument); } } } System.out.println("======================================"); method = Test09.class.getMethod("test02", null); //获取返回值类型 Type genericReturnType = method.getGenericReturnType(); if (genericReturnType instanceof ParameterizedType){ //获得真实类型 Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); //遍历真实类型 for (Type actualTypeArgument : actualTypeArguments) { //真实类型信息:class java.lang.String //真实类型信息:class com.cn.reflect.User System.out.println("真实类型信息:"+actualTypeArgument); } } } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4YNGOAZZ-1638439101818)(D:MarkDown学习imgsreflect26.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JvJiZ9K2-1638439101819)(D:MarkDown学习imgsreflect27.png)]
-
代码案例:
package com.cn.reflect; import java.lang.annotation.*; import java.lang.reflect.Field; //练习反射 *** 作注解 public class Test10 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { //获得类的对象 Class c1 = Class.forName("com.cn.reflect.Stu"); //通过反射获得注解 Annotation[] annotations = c1.getAnnotations(); for (Annotation annotation : annotations) { //@com.cn.reflect.Stu$Tables(value=db_student) System.out.println(annotation); } //获得注解Value的值 Stu.Tables table = (Stu.Tables) c1.getAnnotation(Stu.Tables.class); String value = table.value(); //db_student System.out.println(value); //获得类的指定注解 Field field = c1.getDeclaredField("name"); Stu.Field annotation = field.getAnnotation(Stu.Field.class); //db_name //varchar //50 System.out.println(annotation.columnName()); System.out.println(annotation.type()); System.out.println(annotation.length()); } } //创建一个实体类 @Stu.Tables("db_student") class Stu{ @Field(columnName = "db_name",type = "varchar",length = 50) private String name; @Field(columnName = "db_id",type = "int",length = 20) private int id; @Field(columnName = "db_age",type = "int",length = 20) private int age; public Stu() { } public Stu(String name, int id, int age) { this.name = name; this.id = id; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Stu{" + "name='" + name + ''' + ", id=" + id + ", age=" + age + '}'; } //类名的注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Tables{ String value(); } //属性的注解 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface Field{ String columnName(); String type(); int length(); } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P4vY4I8p-1638439101820)(D:MarkDown学习imgsanno1.png)]
2>内置注解[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dtYNHNI7-1638439101820)(D:MarkDown学习imgsanno2.png)]
3>自定义注解[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xF5pD81e-1638439101854)(D:MarkDown学习imgsanno3.png)]
4>元注解[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lv17AuXZ-1638439101857)(D:MarkDown学习imgsanno4.png)]
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)