【类加载器反射】
第一章 类加载器
1.1 类的加载时机
类(类的.class文件)的加载时机
1. 创建类的实例。
2. 类的静态变量,或者为静态变量赋值。
3. 类的静态方法。
4. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象。
5. 初始化某个类的子类。
6. 直接使用java.exe命令来运行某个主类。
1.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 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
|
public class MyTest04 { public static void main(String[] args) { ClassLoader app = ClassLoader.getSystemClassLoader(); ClassLoader app2 = MyTest04.class.getClassLoader();
System.out.println(app); System.out.println(app2); System.out.println(app2 == app);
System.out.println("---------------------"); ClassLoader p1 = ClassLoader.getPlatformClassLoader(); ClassLoader p2 = app.getParent(); System.out.println(p1); System.out.println(p2); System.out.println(p2==p1);
System.out.println("---------------------"); ClassLoader c1 = String.class.getClassLoader(); ClassLoader c2 = p1.getParent(); System.out.println(c1); System.out.println(c2); } }
|
1 2 3 4 5 6 7
| public class MyTest05 { public static void main(String[] args) { InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("1.txt"); System.out.println(inputStream); } }
|
第二章 反射
2.1 Class类的介绍
1 2 3 4 5 6 7
| 注意: 1.java文件编译生成.class文件,java文件中的内容就是.class文件中的内容, 只不过.class文件是给JVM看的(称为字节码文件) 2.java是面向对象的编程语言,任何事物都可以定义类,并创建对象, .class文件也是一种事物,也可以定义类,创建对象 3.jdk中有个类java.lang.Class,是专门用来描述.class文件的 4.该Class类也是有对象的,但是程序员无法自己创建,由jvm帮助创建,程序员可以获取到该Class类型的对象,从而完成相关的操作
|

2.2 反射的介绍
1 2 3 4 5 6 7 8 9
| 注意: 1.当第一次使用类的信息时,该类的.class文件,会被加载到内存中的方法区中 2.jvm同时为加载到内存方法区的.class文件,创建一个Class类型的对象,该对象被保存在堆内存中 相当于堆内存中的Class类型的对象,指向了方法区的.class文件 3.一个类的.class文件,只能被加载一次,所以对应的Class类型的对象,只有一个 4.任意类型(基本类型/引用类型)都有对应的Class类型的对象 什么叫做反射呢? 通过获取Class类型的对象,从而操作对应的.class文件 说白了: 通过Class类型的对象获取.class文件中的成员变量/成员方法/构造方法并执行
|
反射技术,指的是加载类的字节码到内存,并以编程的方法解刨出类中的各个成分(成员变量、方法、构造器等)

反射有啥用呢?
其实反射是用来写框架用的。平时我们用IDEA开发程序时,用对象调用方法,IDEA会有代码提示,idea会将这个对象能调用的方法都给你列举出来,供你选择,如果下图所示

问题是IDEA怎么知道这个对象有这些方法可以调用呢?
原因是对象能调用的方法全都来自于类,IDEA通过反射技术就可以获取到类中有哪些方法,并且把方法的名称以提示框的形式显示出来,所以你能看到这些提示了。
反射具体学什么?
因为反射获取的是类的信息,那么反射的第一步首先获取到类才行。
由于Java的设计原则是万物皆对象,获取到的类其实也是以对象的形式体现的,叫字节码对象,用Class类来表示。
获取到字节码对象之后,再通过字节码对象就可以获取到类的组成成分了,这些组成成分其实也是对象,
其中每一个成员变量用Field类的对象来表示、
每一个成员方法用Method类的对象来表示,
每一个构造器用Constructor类的对象来表示。
如下图所示:

2.4 三种方式获取字节码文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
|
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
| public class Test06 { public static void main(String[] args) throws Exception { Class a1 = Class.forName("com.zxq._06_获取字节码文件对象.A"); Class b1 = Class.forName("com.zxq._06_获取字节码文件对象.B");
Class a2 = A.class; Class a3 = new A().getClass(); Class a4 = new A().getClass(); System.out.println(a1 == a2); System.out.println(a3 == a2); System.out.println(a3 == a4);
System.out.println(a1 == b1);
System.out.println("----------------"); Class b2 = B.class; Class b3 = new B().getClass(); Class b4 = new B().getClass(); System.out.println(b1==b2); System.out.println(b3==b2); System.out.println(b3==b4); } }
public class A { } public class B { }
|
2.5 反射获取构造方法
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
|
|
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
| public class C { private int a; private double b; private String c;
private C(String c) { this.c = c; }
public C(double b) { this.b = b; }
private C(int a) { this.a = a; }
public C() { }
public C(int a, double b, String c) { this.a = a; this.b = b; this.c = c; }
@Override public String toString() { return "C{" + "a=" + a + ", b=" + b + ", c='" + c + '\'' + '}'; } }
|
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
| public class TestC { public static void main(String[] args) throws Exception { Class clazz = C.class; Constructor[] arr1 = clazz.getConstructors(); System.out.println(Arrays.toString(arr1));
Constructor[] arr2 = clazz.getDeclaredConstructors(); System.out.println(Arrays.toString(arr2));
Constructor c1 = clazz.getConstructor();
System.out.println(c1); Object o = c1.newInstance(); System.out.println(o);
Constructor c2 = clazz.getConstructor(int.class, double.class, String.class); System.out.println(c2);
Object o1 = c2.newInstance(100, 200.1, "嘿嘿"); System.out.println(o1);
System.out.println("=================================="); Constructor c3 = clazz.getDeclaredConstructor(int.class); System.out.println(c3); c3.setAccessible(true); Object o2 = c3.newInstance(666); System.out.println(o2);
System.out.println("--------------------------------"); Object o3 = clazz.newInstance(); System.out.println(o3); } }
|
2.10 反射获取成员方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class D { private void show1(){ System.out.println("私有的show1..."); } private void show1(double a){ System.out.println("私有的show1...a="+a); } public int show2(int a){ System.out.println("公共的的show2...a="+a); return 2*a; } public void show2(int a,int b){ System.out.println("公共的的show2...a="+a+",b="+b); } }
|
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
| public class TestD { public static void main(String[] args) throws Exception { Class cz = D.class; Object o = cz.newInstance();
Method[] arr = cz.getMethods(); System.out.println(Arrays.toString(arr));
Method[] arr2 = cz.getDeclaredMethods(); System.out.println(Arrays.toString(arr2));
Method m1 = cz.getMethod("show2", int.class); Object invoke = m1.invoke(o, 123); System.out.println("方法返回的结果是:"+invoke);
Method m2 = cz.getMethod("show2", int.class, int.class); Object invoke1 = m2.invoke(o, 2, 5); System.out.println(invoke1);
Method m3 = cz.getDeclaredMethod("show1", double.class); m3.setAccessible(true); Object invoke2 = m3.invoke(o, 2.2); System.out.println(invoke2); } }
|
2.11反射获取成员属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class E { private String name; private int age; private double score;
@Override public String toString() { return "E{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + '}'; } }
|
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
| public class TestE { public static void main(String[] args) throws Exception { Class cz = E.class; Object o = cz.newInstance();
Field[] arr = cz.getDeclaredFields(); System.out.println(Arrays.toString(arr));
Field name = cz.getDeclaredField("name"); name.setAccessible(true);
System.out.println(o); name.set(o,"张三"); System.out.println(o);
Field age = cz.getDeclaredField("age"); Field score = cz.getDeclaredField("score"); age.setAccessible(true); score.setAccessible(true);
age.set(o,18); score.set(o,99.8); System.out.println(o);
System.out.println(age.get(o)); System.out.println(score.get(o)); } }
|
2.13 反射案例分析
1 2 3 4 5 6
| className=com.example.UserService
methodName=sayHello
param=灵星智能商城
|
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
|
public class MyTools1 { private MyTools1(){}
public static Object start() throws Exception {
InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream("my.conf");
Properties p = new Properties();
InputStreamReader isr = new InputStreamReader(in,"utf-8");
p.load(isr);
String className = p.getProperty("className");
Class c = Class.forName(className);
Method method = c.getMethod(p.getProperty("methodName"), String.class);
return method.invoke(c.newInstance(),p.getProperty("param")); } }
|
1 2 3 4 5 6
| public class A { public String abc(String s){ System.out.println("A类的abc方法执行的时候,得到的参数是:"+s); return s+s; } }
|
1 2 3 4 5 6
| public class B { public Integer bbc(String s){ System.out.println("B类的bbc方法执行的时候,得到的参数是:"+s); return Integer.parseInt(s)*2; } }
|
1 2 3 4 5 6 7
| public class Test01 { public static void main(String[] args) throws Exception { Object start = MyTools1.start(); System.out.println("工具返回的结果是:"+start); } }
|
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
|
public class Test02 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { List<Integer> list = new ArrayList<>(); list.add(123);
Class c = list.getClass(); Method add = c.getMethod("add", Object.class); add.invoke(list,"abc"); System.out.println(list);
String name = add.getName(); Class returnType = add.getReturnType(); Class[] parameterTypes = add.getParameterTypes();
Class aClass = add.getDeclaringClass(); String simpleName = aClass.getSimpleName(); String name1 = aClass.getName(); System.out.println("反射的add是:"+simpleName+"类("+name1+")下的:"+name+",参数类型是:"+ Arrays.toString(parameterTypes)+",返回值类型是"+returnType); } }
|