首先了解一下类的概念
-
类是如何加载的?
1.加载
将类的.class文件加载到方法区
创建一个Class对象(表示就是.class文件)相对于文件的对象
2.连接
验证: 验证一下类的内部结构(成员变量 和 方法)
准备: 为静态变量开辟空间 赋初始值
解析: 将局部变量进行替换 替换成对应值
3.初始化
创建对象 new对象(堆内存开辟空间 跟之前一样) -
类是什么时候被加载的?(加载时机)
1.当你使用类的时候, 该类一定会被加载
2.加载该类时会先加载该类父类 -
类是用什么加载的?(使用类加载器加载类)
1.根加载器: 加载jdk的lib文件夹下的jar文件
2.扩展加载器: 加载ext文件夹下的文件
3.系统加载器: 咱们自定义类或者导入jar都用系统加载器
了解完类的概念,现在来了解一下反射
- 反射可以将一个正在运行的类(加载完成的类), 通过这个Class文件的对象, 可以直接获取类内部的所有方法和成员变量(包括私有的)
获取Class文件对象方法
1.通过对象获取
2.通过类获取
3.通过Class中的静态方法获取(Class.forName() 常用)
首先创建一个类:
public class Person {
public String name;
private int age;
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
// 私有构造方法
public Person(int age, String name) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
// 吃饭
public void eat() {
System.out.println("吃饭");
}
// 说话
public void speak(String str) {
System.out.println("说的是:" + str);
}
// 打游戏
private int play(String game) {
System.out.println("玩的是:" + game);
return 123;
}
}
获取Class文件对象方法如下:
// 通过对象获取
Person p = new Person();
// 获取Person类的 Class文件对象
Class<? extends Person> c1 = p.getClass();
// 全类名
System.out.println(c1);
// 通过类获取
Class<Person> c2 = Person.class;
System.out.println(c2);
// 常用(只需要一个字符串 就能获取该类的Class对象)
// 注意:参数 要填全类名 包名+类名
Class<?> c3 = Class.forName("com.lanou3g.reflect.Person");
System.out.println(c3);
创建对象
// 通过Class文件对象 获取类中构造方法
Class<?> c = Class.forName("com.lanou3g.reflect.Person");
// 获取所有public共有的构造方法
Constructor<?>[] constructors = c.getConstructors();
// 遍历
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
// 获取单个构造方法
Constructor<?> constructor = c.getConstructor();
// 利用该构造方法创建对象
Object object = constructor.newInstance();
System.out.println(object);
// 有参构造创建对象(参数是参数类的文件类型)
Constructor<?> constructor2 = c.getConstructor(String.class,int.class);
// 创建对象
Object object2 = constructor2.newInstance("旺旺",30);
System.out.println(object2);
通过Class文件对象快速创建对象
前提:
1.类必须用public
2.必须提供无参构造方法
3.该无参的构造方法必须是public修饰
Class<?> c = Class.forName("com.lanou3g.reflect.Person");
// 快速创建对象(直接使用类中 无参构造方法创建的)
Object object = c.newInstance();
System.out.println(object);
获取构造方法,代码如下:
// 获取类中所有的构造方法(包括私有)
Class<?> c = Class.forName("com.lanou3g.reflect.Person");
Constructor<?>[] constructors = c.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
// 获取私有的构造方法
Constructor<?> constructorP = c.getDeclaredConstructor(int.class,String.class);
// 打开私有方法使用权限
constructorP.setAccessible(true);
// 创建对象
Object object = constructorP.newInstance(30,"wl");
// 打印对象
System.out.println(object);
获取成员变量
// 获取所有公开成员变量
Class<?> c = Class.forName("com.lanou3g.reflect.Person");
Field[] fields = c.getFields();
for (Field field : fields) {
System.out.println(field);
}
// 单独获取指定成员变量
Field field = c.getField("name");
// 创建一个Person
Object object = c.newInstance();
// 通过反射 给该属性赋值
field.set(object, "东东");
System.out.println(object);
// 获取私有成员变量 age 并赋值 打印
Field ageField = c.getDeclaredField("age");
// 打开访问权限
ageField.setAccessible(true);
ageField.set(object, 26);
System.out.println(object);
获取成员方法
Class<?> c = Class.forName("com.lanou3g.reflect.Person");
// 获取类中所有的公开方法(包括父类的)
Method[] methods = c.getMethods();
for (Method method : methods) {
System.out.println(method);
}
// 获取指定的成员方法
// 参数1: 获取的方法名字
// 参数2: 获取的方法的参数的Class类型
Method method = c.getMethod("eat");
Object object = c.newInstance();
// 调用该方法
// 参数1: 调用该方法的对象
// 参数2: 调用该方法 要传入的参数
// 返回值: 调用该方法 方法的返回值
Object rel = method.invoke(object);
System.out.println(rel);
Method method2 = c.getMethod("speak", String.class );
Object rel2 = method2.invoke(object,"国语");
System.out.println(rel2);
Method method3 = c.getDeclaredMethod("play",String.class);
// 开启权限
method3.setAccessible(true);
// 调用方法
Object rel3 = method3.invoke(object, "LOL");
System.out.println(rel3);