JavaStudy12(23章-反射)—B站hsp
1.1 一个需求引出反射
1.1.1请看下面的问题
代码演示:
package com.hspedu.reflection.question;
import com.hspedu.Cat;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @ClassName ReflectionQuestion
* @Author :BLWY-1124
* @Date :2022/5/1 17:16
* @Description:
* 反射问题的引入
* @Version: 1.0
*/
@SuppressWarnings({"all"})
public class ReflectionQuestion {
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//根据配置文件 re.properties指定信息,创建Cat对象并调用方法hi
//回忆
//传统方式 new 对象 =》 调用
//Cat cat = new Cat();
//cat.hi();
//我们尝试做一做 -》明白反射
//1. 使用Properties 类,可以读写配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));//com.hspedu.Cat
String classfullpath = properties.get("classfullpath").toString(); //hi
String methodName = properties.get("method").toString();
System.out.println("classfullpath=" +classfullpath);
System.out.println("method= " + methodName);
//2.创建对象, 传统的方法行不通
//new classfullpath();
//3.使用反射机制解决
//(1)加载类,返回Class类型的对象cls
Class cls =Class.forName(classfullpath);
//(2)通过cls获得到你加载的类 com.hspedu.Cat 的对象实例
Object o = cls.newInstance();
System.out.println(o.getClass()); //com.hspedu.Cat 运行类型
//(3)通过cls 得到加载的类(com.hspedu.Cat)的 methodName(hi) 的方法对象
// 即:在反射中,可以把方法视为对象(万物皆对象 )
Method method = cls.getMethod(methodName); //对象 :method
// (4)通过 method 调用方法:即通过方法对象来实现调用方法
method.invoke(o); // 传统方法 对象.方法() ,反射机制 方法.invoke(对象)
}
}
/**
* @ClassName Cat
* @Author :BLWY-1124
* @Date :2022/5/1 17:13
* @Description:
* @Version: 1.0
*/
public class Cat {
private String name = "招财猫";
public void hi(){//常用方法
System.out.println("hi" + name);
}
public void cry(){//常用方法
System.out.println("cry" + name);
}
}
配置文件
1.2 反射机制
1.2.1 Java Reflection
1.2.2 Java 反射机制原理示意图!!!
1.2.3 Java 反射机制可以完成
1.2.4 反射相关的主要类
代码演示:
package com.hspedu.reflection;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @ClassName Reflection01
* @Author :BLWY-1124
* @Date :2022/5/4 20:10
* @Description:
* @Version: 1.0
*/
public class Reflection01 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.get("classfullpath").toString();
String methodName = properties.get("method").toString();
//3.使用反射机制解决
//(1)加载类,返回Class类型的对象cls
Class cls =Class.forName(classfullpath);
//(2)通过cls获得到你加载的类 com.hspedu.Cat 的对象实例
Object o = cls.newInstance();
System.out.println(o.getClass()); //com.hspedu.Cat 运行类型
//(3)通过cls 得到加载的类(com.hspedu.Cat)的 methodName(hi) 的方法对象
// 即:在反射中,可以把方法视为对象(万物皆对象 )
Method method = cls.getMethod(methodName); //对象 :method
// (4)通过 method 调用方法:即通过方法对象来实现调用方法
method.invoke(o); // 传统方法 对象.方法() ,反射机制 方法.invoke(对象)
//4.java.lang.reflect.Field: 代表类的成员变量, Field 对象表示某个类的成员变量
// 得到 name 字段
// getField 不能得到私有的属性
// Field name = cls.getField("name"); private
Field ageField = cls.getField("age");
System.out.println(ageField.get(o)); //传统写法 对象.成员变量 反射:成员变量对象.get(对象)
//5.java.lang.reflect.Constructor: 代表类的构造方法, Constructor 对象表示构造器
Constructor constructor = cls.getConstructor(); //()中可以指定构造器参数类型,返回无参构造
System.out.println(constructor); //public com.hspedu.Cat()
Constructor constructor1 = cls.getConstructor(String.class); //这里传入的就是 String.class类的Class对象
System.out.println(constructor1); //public com.hspedu.Cat(java.lang.String)
}
}
package com.hspedu;
/**
* @ClassName Cat
* @Author :BLWY-1124
* @Date :2022/5/1 17:13
* @Description:
* @Version: 1.0
*/
public class Cat {
private String name = "招财猫";
public int age = 12;
public Cat(String name) {
this.name = name;
}
public Cat() {
}
public void hi(){//常用方法
System.out.println("hi" + name);
}
public void cry(){//常用方法
System.out.println("cry" + name);
}
}
配置文件
1.2.5 反射优点和缺点
hi.setAccessible(true);//在反射调用方法时,取消访问检查 提升执行效率
代码演示:
package com.hspedu.reflection;
import com.hspedu.Cat;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @ClassName Reflection02
* @Author :BLWY-1124
* @Date :2022/5/4 20:38
* @Description: 测试反射调用的性能,和优化方案
* @Version: 1.0
*/
public class Reflection02 {
public static void main(String[] args) throws NoSuchMethodException, IOException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
//Field
// Method
// Constructor
m1();//传统
m2();//反射
m3();//取消访问检查
}
//传统方法来调用 hi
public static void m1() {
Cat cat = new Cat();
long start = System.currentTimeMillis();
for (int i = 0; i <900000000; i++) {
cat.hi();
}
long end = System.currentTimeMillis();
System.out.println("传统方法来调用时间m1=" + (end - start));
}
//反射机制调用方法 hi
public static void m2() throws ClassNotFoundException, NoSuchMethodException, IOException, InvocationTargetException, IllegalAccessException, InstantiationException {
/*Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.get("classfullpath").toString();
Class cls = Class.forName(classfullpath);*/
Class cls = Class.forName("com.hspedu.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
long start = System.currentTimeMillis();
for (int i = 0; i <900000000; i++) {
hi.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射m2=" + (end - start));
}
//反射机制调用方法 hi 在反射调用方法时,取消访问检查
public static void m3() throws ClassNotFoundException, NoSuchMethodException, IOException, InvocationTargetException, IllegalAccessException, InstantiationException {
/*Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.get("classfullpath").toString();
Class cls = Class.forName(classfullpath);*/
Class cls = Class.forName("com.hspedu.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
hi.setAccessible(true);//在反射调用方法时,取消访问检查
long start = System.currentTimeMillis();
for (int i = 0; i <900000000; i++) {
hi.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射m2=" + (end - start));
}
}
1.2.6 反射调用优化-关闭访问检查
1.3 Class 类
1.3.1 基本介绍
代码演示:
package com.hspedu.reflection.class_;
import com.hspedu.Cat;
/**
* @ClassName Class01
* @Author :BLWY-1124
* @Date :2022/5/5 10:17
* @Description: 对 Class 类特点的梳理
* @Version: 1.0
*/
public class Class01 {
public static void main(String[] args) throws ClassNotFoundException {
//看看 Class 类图
// 1. Class 也是类,因此也继承 Object 类
// Class
// 2. Class 类对象不是 new 出来的,而是系统创建的
// (1) 传统 new 对象
/*public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}*/
//Cat cat = new Cat();
// (2) 反射方式, 刚才老师没有 debug 到 ClassLoader 类的 loadClass, 原因是,我没有注销 Cat cat = new Cat();
/*
ClassLoader 类, 仍然是通过 ClassLoader 类加载 Cat 类的 Class 对象
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}*/
Class cls01 = Class.forName("com.hspedu.Cat");
//3. 对于某个类的 Class 类对象,在内存中只有一份,因为类只加载一次
Class cls02 = Class.forName("com.hspedu.Cat");
System.out.println(cls01.hashCode()); //460141958
System.out.println(cls02.hashCode()); //460141958
Class cls03 = Class.forName("com.hspedu.Dog");
System.out.println(cls03.hashCode()); //1163157884
}
}
1.3.2 Class 类的常用方法
1.3.3 应用实例: Class02.java
代码演示:
package com.hspedu.reflection.class_;
import com.hspedu.Car;
import java.lang.reflect.Field;
import java.util.Base64;
/**
* @BelongsProject: chapte23r
* @BelongsPackage: com.hspedu.reflection.class_
* @Author: 别来无恙qb
* @CreateTime: 2022-05-05 11:27
* @Description: 演示Class类的常用方法
*/
public class Class02 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
String classPath = "com.hspedu.Car";
//1.获取到 Car 类的 对应的 Class对象
//<?> 表示不确定Java类型
Class<?> cls = Class.forName(classPath);
//2.输出
System.out.println(cls); //显示对象,是哪个Class类的对象: com.hspedu.Car
System.out.println(cls.getClass()); // cls 运行类型:java.lang.Class
//3.得到包名
System.out.println(cls.getPackage().getName()); // com.hspedu cls对应的Class类在哪一个包下面
//4. 得到 cls 对应类的全类名
System.out.println(cls.getName()); // com.hspedu.Car
//5.通过cls 生成对象实例
//Object o = cls.newInstance();
Car car = (Car) cls.newInstance();
System.out.println(car); //Car{brand='宝马', price=550000, color='蓝色'}
//6. 通过反射获得属性 brand
Field brand = cls.getField("brand");
System.out.println(brand.get(car)); //宝马
//7.通过反射给属性赋值
brand.set(car,"奔驰");
System.out.println(brand.get(car)); //奔驰
//8.得到所有的属性(字段)
Field[] fields = cls.getFields();
for (Field field : fields) {
System.out.print("\t" + field.getName()); //属性名称 //brand price color
}
}
}
1.4 获取 Class 类对象
代码演示:
package com.hspedu.reflection.class_;
import com.hspedu.Car;
/**
* @BelongsProject: chapte23r
* @BelongsPackage: com.hspedu.reflection.class_
* @Author: 别来无恙qb
* @CreateTime: 2022-05-05 12:09
* @Description: 演示得到Class的各种方式
*/
public class GetClass {
public static void main(String[] args) throws ClassNotFoundException {
//1. Class.forName
/*Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.get("classfullpath").toString();*/
String classAllPath = "com.hspedu.Car"; //通过读取配置文件获取
Class<?> cls1 = Class.forName(classAllPath);
System.out.println(cls1); //class com.hspedu.Car
//2. 类名.class , 应用场景: 用于参数传递
Class<Car> cls2 = Car.class;
System.out.println(cls2);//class com.hspedu.Car
//3.对象.getClass(), 应用场景,有对象实例
Car car = new Car();
Class cls3 = car.getClass();
System.out.println(cls3); //class com.hspedu.Car
//4. 通过类加载器【4 种】来获取到类的 Class 对象
// (1)先得到类加载器 car
ClassLoader classLoader = car.getClass().getClassLoader();
//(2)通过类加载器得到 Class 对象
Class<?> cls4 = classLoader.loadClass(classAllPath);
System.out.println(cls4); // class com.hspedu.Car
//cls1 , cls2 , cls3 , cls4 其实是同一个对象
System.out.println(cls1.hashCode()); //356573597
System.out.println(cls2.hashCode()); //356573597
System.out.println(cls3.hashCode()); //356573597
System.out.println(cls4.hashCode()); //356573597
//5. 基本数据(int, char,boolean,float,double,byte,long,short) 按如下方式得到 Class 类对象
Class<Integer> integerClass = int.class;
Class<Character> characterClass = char.class;
Class<Boolean> booleanClass = boolean.class;
System.out.println(integerClass); //int 自动装箱和拆箱
System.out.println(characterClass); //char
System.out.println(booleanClass); //boolean
//6. 基本数据类型对应的包装类,可以通过 .TYPE 得到 Class 类对象
Class<Integer> integerClass1 = Integer.TYPE;
Class<Character> characterClass1 = Character.TYPE;
Class<Boolean> booleanClass1 = Boolean.TYPE;
System.out.println(integerClass1); //int 自动装箱和拆箱
//是同一个class对象
System.out.println(integerClass.hashCode()); //1735600054
System.out.println(integerClass1.hashCode()); //1735600054
}
}
1.5 哪些类型有 Class 对象
1.5.1 如下类型有 Class 对象
代码演示:
package com.hspedu.reflection.class_;
import java.io.Serializable;
/**
* @BelongsProject: chapte23r
* @BelongsPackage: com.hspedu.reflection.class_
* @Author: 别来无恙qb
* @CreateTime: 2022-05-05 13:09
* @Description: 演示哪些类型有 Class 对象
*/
public class AllTypeClass {
public static void main(String[] args) {
Class<String> cls1 = String.class; //外部类
Class<Serializable> cls2 = Serializable.class;//接口
Class<Integer[]> cls3 = Integer[].class; //数组
Class<float[][]> cls4 = float[][].class; //二维数组
Class<Deprecated> cls5 = Deprecated.class; //注解
//枚举
Class<Thread.State> cls6 = Thread.State.class;
Class<Long> cls7 = long.class; //基本类型
Class<Void> cls8 = void.class; //void数据类型
Class<Class> cls9 = Class.class;//
System.out.println(cls1); //class java.lang.String
System.out.println(cls2); //interface java.io.Serializable
System.out.println(cls3); //class [Ljava.lang.Integer;
System.out.println(cls4); //class [[F
System.out.println(cls5); //interface java.lang.Deprecated
System.out.println(cls6); //class java.lang.Thread$State
System.out.println(cls7); //long
System.out.println(cls8); //void
System.out.println(cls9); //class java.lang.Class
}
}
1.6 类加载
1.6.1 基本说明
代码演示
import java.util. *;
import java.lang.relfect. *;
public class ClassLoad_ {
public static void mian(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入key");
String key = scanner.next();
switch (key) {
case "1":
//Dog dog = new Dog(); //静态加载,依赖性强,在编译时就要加载一遍
//dog.cry();
break;
case "2":
//反射-》动态加载
Class cls = Class.forName("Person");//加载Person
Object o = cls.newInstance();
Method m = cls.getMethod("hi");
m.invoke(o);
System.out.println("ok");
break;
default:
java
System.out.println("nothing");
}
}
}
1.6.2 类加载时机
1.6.3 类加载过程图
1.6.4 类加载各阶段完成任务
1.6.5 加载阶段
1.6.6 连接阶段-验证
1.6.7 连接阶段-准备
1.6.8 连接阶段-解析
1.6.9 Initialization(初始化)
代码演示:
/**
* @BelongsProject: chapte23r
* @BelongsPackage: com.hspedu.reflection.classload_
* @Author: 别来无恙qb
* @CreateTime: 2022-05-05 20:07
* @Description: 演示类加载-初始化阶段
*/
public class ClassLoad03 {
public static void main(String[] args) {
//分析
//1. 加载 B 类,并生成 B 的 class 对象
// 2. 链接 num = 0
// 3. 初始化阶段
// 依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并合并
// /* clinit() {
// System.out.println("B 静态代码块被执行");
// num = 300;
// num = 100;
// }
// 合并: num = 100 */
// new B();
// 类加载
// System.out.println(B.num);//100, 如果直接使用类的静态属性,也会导致类的加载
//看看加载类的时候,是有同步机制控制
/*protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException
{
//正因为有这个机制,才能保证某个类在内存中, 只有一份 Class 对象
synchronized (getClassLoadingLock(name)) {
//....
}
} */
B b = new B();
}
}
class B {
static {
System.out.println("B 静态代码块被执行");
num = 300;
}
static int num = 100;
public B() {//构造器 System.out.println("B() 构造器被执行");
}
1.7 通过反射获取类的结构信息
1.7.1 第一组: java.lang.Class 类
1.7.2 第二组: java.lang.reflect.Field 类
1.7.3 第三组: java.lang.reflect.Method 类
1.7.4 第四组: java.lang.reflect.Constructor 类
代码演示:
package com.hspedu.reflection;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @BelongsProject: chapte23r
* @BelongsPackage: com.hspedu.reflection
* @Author: 别来无恙qb
* @CreateTime: 2022-05-05 21:14
* @Description: 演示如何通过反射获取类的结构信息
*/
public class ReflectionUtils {
public static void main(String[] args) {
}
//第一组方法API
@Test
public void api_01() throws ClassNotFoundException {
//得到 Class 对象
Class<?> personCls = Class.forName("com.hspedu.reflection.Person");
//getName:获取全类名
System.out.println(personCls.getName()); //com.hspedu.reflection.Person
//getSimpleName:获取简单类名
System.out.println(personCls.getSimpleName());//Person
//getFields:获取所有 public 修饰的属性,包含本类以及父类的
Field[] fields = personCls.getFields();
System.out.println("本类以及父类的属性=");
for (Field field : fields) { //增强for循环
System.out.print("\t" + field.getName());//name hobby
}
//getDeclaredFields:获取本类中所有属性
Field[] declaredFields = personCls.getDeclaredFields();
System.out.println("本类中所有属性=");
for (Field declaredField : declaredFields) {
System.out.print("\t" + declaredField.getName());
//本类中所有属性= name age job sal
}
//getMethods:获取所有 public 修饰的方法,包含本类以及父类的
Method[] methods = personCls.getMethods();
System.out.print("本类以及父类的方法=");
for (Method method : methods) {
System.out.print("\t" + method.getName());
//本类以及父类的方法= m1 hi wait wait wait equals toString hashCode getClass notify notifyAll
}
//getDeclaredMethods:获取本类中所有方法
Method[] declaredMethods = personCls.getDeclaredMethods();
System.out.println("本类所有的方法=");
for (Method declaredMethod : declaredMethods) {
System.out.print("\t" + declaredMethod.getName());
//本类所有的方法= m1 m2 m4 m3
}
//getConstructors: 获取所有 public 修饰的构造器,包含本类
Constructor<?>[] constructors = personCls.getConstructors();
System.out.println("本类的构造器=");
for (Constructor<?> constructor : constructors) {
System.out.print("\t" + constructor.getName());
//本类的构造器=com.hspedu.reflection.Person com.hspedu.reflection.Person
}
//getDeclaredConstructors:获取本类中所有构造器
Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
System.out.println("本类中所有构造器=");
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.print("\t" + declaredConstructor.getName()); //这里只是输出名
//本类中所有构造器= com.hspedu.reflection.Person com.hspedu.reflection.Person com.hspedu.reflection.Person
}
//getPackage:以 Package 形式返回 包信息
Package aPackage = personCls.getPackage();
System.out.println(aPackage.getName());//com.hspedu.reflection
//getSuperClass:以 Class 形式返回父类信息
Class<?> superclass = personCls.getSuperclass();
System.out.println("父类的 class 对象=" + superclass);//class java.lang.Object
//getInterfaces:以 Class[]形式返回接口信息
Class<?>[] interfaces = personCls.getInterfaces();
System.out.println("接口信息=");
for (Class<?> anInterface : interfaces) {
System.out.print("\t" + anInterface);
//interface com.hspedu.reflection.IA interface com.hspedu.reflection.IB
}
//getAnnotations:以 Annotation[] 形式返回注解信息
Annotation[] annotations = personCls.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("注解信息=" + annotation); //注解
//注解信息=@java.lang.Deprecated()
}
}
@Test
public void api_02() throws ClassNotFoundException {
//得到 Class 对象
Class<?> personCls = Class.forName("com.hspedu.reflection.Person");
//第二组:java.lang.reflect.Field 类
//getModifiers: 以int形式返回修饰符
//getDeclaredFields:获取本类中所有属性
//规定 说明: 默认修饰符 是 0 , public 是 1 ,private 是 2 ,protected 是 4 , static 是 8 ,final 是 16
Field[] declaredFields = personCls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本类中所有属性=" + declaredField.getName() +
" 该属性的修饰符值= " + declaredField.getModifiers() +
" 该属性的类型=" + declaredField.getType());//属性对应的类的class对象
//本类中所有属性=name 该属性的修饰符值= 1 该属性的类型=class java.lang.String
//本类中所有属性=age 该属性的修饰符值= 12 该属性的类型=int
//本类中所有属性=job 该属性的修饰符值= 0 该属性的类型=class java.lang.String
//本类中所有属性=sal 该属性的修饰符值= 2 该属性的类型=double
}
//第三组: java.lang.reflect.Method 类
//getModifiers: 以int形式返回修饰符
//getDeclaredMethods:获取本类中所有方法
Method[] declaredMethods = personCls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本类中所有方法=" + declaredMethod.getName() +
" 该方法的访问修饰符值=" + declaredMethod.getModifiers() +
" 该方法返回类型" + declaredMethod.getReturnType());
//本类中所有方法=m1 该方法的访问修饰符值=1 该方法返回类型void
//本类中所有方法=m2 该方法的访问修饰符值=4 该方法返回类型class java.lang.String
//本类中所有方法=m4 该方法的访问修饰符值=2 该方法返回类型void
//本类中所有方法=m3 该方法的访问修饰符值=0 该方法返回类型void
//输出当前这个方法的形参数组情况 m1的形参情况 m2m3m4没有形参
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("该方法的形参类型=" + parameterType);
//该方法的形参类型=class java.lang.String
//该方法的形参类型=int
//该方法的形参类型=double
}
}
//第四组: java.lang.reflect.Constructor 类
//getModifiers: 以int形式返回修饰符
//getConstructors: 获取所有 public 修饰的构造器,包含本类
Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println("====================");
System.out.println("本类中所有构造器=" + declaredConstructor.getName());//这里老师只是输出名
Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("该构造器的形参类型=" + parameterType);
}
//====================
//本类中所有构造器=com.hspedu.reflection.Person
//该构造器的形参类型=class java.lang.String
//该构造器的形参类型=int
//====================
//本类中所有构造器=com.hspedu.reflection.Person
//该构造器的形参类型=class java.lang.String
//====================
//本类中所有构造器=com.hspedu.reflection.Person
}
}
}
class A {
public String hobby;
public void hi() {
}
}
interface IA {
}
interface IB {
}
@Deprecated
class Person extends A implements IA, IB {
//属性
public String name;
protected static int age; // 4 + 8 = 12
String job;
private double sal;
//构造器
public Person() {
}
public Person(String name) {
}
//私有的构造器
private Person(String name, int age) {
}
//方法
public void m1(String name, int age, double sal) {
}
protected String m2() {
return null;
}
void m3() {
}
private void m4() {
}
}
1.8 通过反射创建对象
1.8.1 案例演示 com.hspedu.reflection ReflecCreateInstance.java
- 测试 1:通过反射创建某类的对象,要求该类中必须有 public 的无参构造
- 测试 2:通过调用某个特定构造器的方式,实现创建某类的对象
代码演示
package com.hspedu.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.channels.ClosedSelectorException;
/**
* @BelongsProject: chapte23r
* @BelongsPackage: com.hspedu.reflection
* @Author: 别来无恙qb
* @CreateTime: 2022-05-06 10:32
* @Description: 演示通过反射机制创建实例
*/
public class ReflecCreateInstance {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//1. 先获取到 User 类的 Class 对象
Class<?> userCls = Class.forName("com.hspedu.reflection.User");
//2. 通过 public 的无参构造器创建实例
Object o = userCls.newInstance();
System.out.println(o); // User [age=10, name=韩顺平教育]
//3. 通过 public 的有参构造器创建实例
/*
constructor 对象就是
public User(String name) {//public 的有参构造器
this.name = name;
}*/
//3.1 先得到对应构造器
Constructor<?> constructor = userCls.getConstructor(String.class);
//3.2 创建实例,并传入实参
Object hsp = constructor.newInstance("hsp");
System.out.println("hsp= " + hsp); //hsp= User [age=10, name=hsp]
//4. 通过非 public 的有参构造器创建实例
// 4.1 得到 private 的构造器对象
Constructor<?> declaredConstructor = userCls.getDeclaredConstructor(int.class, String.class);
//4.2 创建实例
//暴破【暴力破解】 , 使用反射可以访问 private 构造器/方法/属性, 反射面前,都是纸老虎
declaredConstructor.setAccessible(true);
Object user2 = declaredConstructor.newInstance(100, "张三");
System.out.println("user2=" + user2);//user2=User [age=100, name=张三]
}
}
class User { //User 类
private int age = 10;
private String name = "韩顺平教育";
public User() {//无参 public
}
public User(String name) {//public 的有参构造器
this.name = name;
}
private User(int age, String name) {//private 有参构造器
this.age = age;
this.name = name;
}
public String toString() {
return "User [age=" + age + ", name=" + name + "]";
}
}
1.9 通过反射访问类中的成员
1.9.1 访问属性 ReflecAccessProperty.java
代码演示:
package com.hspedu.reflection;
import java.lang.reflect.Field;
/**
* @BelongsProject: chapte23r
* @BelongsPackage: com.hspedu.reflection
* @Author: 别来无恙qb
* @CreateTime: 2022-05-06 11:36
* @Description: 演示反射操作属性
*/
public class ReflecAccessProperty {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
//1. 得到 Student 类对应的 Class 对象
Class<?> studentCls = Class.forName("com.hspedu.reflection.Student");
//2. 创建对象
Object o = studentCls.newInstance();//o 的运行类型就是 Student
System.out.println(o.getClass());//class com.hspedu.reflection.Student
//3. 使用反射得到 age 属性对象
Field age = studentCls.getField("age");
age.set(o,55);
System.out.println(o); //Student [age=55, name=null]
System.out.println(age.get(o));//返回 age 属性的值 55
//4. 使用反射操作 private name 属性
Field name = studentCls.getDeclaredField("name");
//对 name 进行暴破, 可以操作 private 属性
name.setAccessible(true);
name.set(o,"覃波");
System.out.println(o);//Student [age=55, name=覃波]
name.set(null, "老韩~");//因为 name 是 static 属性,因此 o 也可以写出 null
System.out.println(o); //Student [age=55, name=老韩~]
System.out.println(name.get(o)); //老韩~ //获取属性值
System.out.println(name.get(null));//老韩~ //获取属性值, 要求 name 是 static
}
}
class Student {//类
public int age;
private static String name;
public Student() {//构造器
}
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
}
1.9.2 访问方法 ReflecAccessMethod.java
代码演示:
package com.hspedu.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @BelongsProject: chapte23r
* @BelongsPackage: com.hspedu.reflection
* @Author: 别来无恙qb
* @CreateTime: 2022-05-06 12:57
* @Description: 演示通过反射调用方法
*/
public class ReflecAccessMethod {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//1. 得到 Boss 类对应的 Class 对象
Class<?> bossCls = Class.forName("com.hspedu.reflection.Boss");
//2. 创建对象
Object o = bossCls.newInstance();
//3. 调用 public 的 hi 方法
//Method hi = bossCls.getMethod("hi", String.class);
//3.1 得到 hi 方法对象
Method hi = bossCls.getDeclaredMethod("hi", String.class);
//3.2 调用
hi.invoke(o, "韩顺平教育"); //hi 韩顺平教育
//4. 调用 private static 方法
// 4.1 得到 say 方法对象
Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
//4.2 因为 say 方法是 private, 所以需要暴破,原理和前面讲的构造器和属性一样
say.setAccessible(true);
System.out.println(say.invoke(o, 5, "你好", 'A'));//5 你好 A
//4.3 因为 say 方法是 static 的,还可以这样调用 ,可以传入 null
System.out.println(say.invoke(null, 7, "你好", 'A'));//7 你好 A
//5. 在反射中,如果方法有返回值,统一返回 Object , 但是他运行类型和方法定义的返回类型一致
Object reVal = say.invoke(null, 30, "你好", '男');
System.out.println("reVal 的运行类型=" + reVal.getClass());//reVal 的运行类型=class java.lang.String
//在演示一个返回的案例
Method m1 = bossCls.getDeclaredMethod("m1");
Object reVal2 = m1.invoke(o);
System.out.println("reVal2 的运行类型=" + reVal2.getClass());//reVal2 的运行类型=class com.hspedu.reflection.Monster
}
}
class Monster {
}
class Boss {//类
public int age;
private static String name;
public Boss() {//构造器
}
public Monster m1() {
return new Monster();
}
private static String say(int n, String s, char c) {//静态方法
return n + " " + s + " " + c;
}
public void hi(String s) {//普通 public 方法
System.out.println("hi " + s);
}
}
1.10 本章作业
代码演示:
package com.hspedu.reflection.homework;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @BelongsProject: chapte23r
* @BelongsPackage: com.hspedu.reflection.homework
* @Author: 别来无恙qb
* @CreateTime: 2022-05-06 14:02
* @Description:
*/
public class HomeWork01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
//Class<?> privateTestClass = Class.forName("com.hspedu.reflection.homework.PrivateTest");
Class<PrivateTest> privateTestClass = PrivateTest.class;
Object o = privateTestClass.newInstance();
Field name = privateTestClass.getDeclaredField("name");
name.setAccessible(true);
name.set(o,"hsp");
Method getName = privateTestClass.getDeclaredMethod("getName");
System.out.println(getName.invoke(o)); //hsp
}
}
class PrivateTest{
private String name = "helloKitty";
public String getName() {
return name;
}
}
代码演示:
package com.hspedu.reflection.homework;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @BelongsProject: chapte23r
* @BelongsPackage: com.hspedu.reflection.homework
* @Author: 别来无恙qb
* @CreateTime: 2022-05-06 14:22
* @Description:
*/
public class HomeWork02 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//Class<File> fileClass = File.class;
Class<?> fileClass = Class.forName("java.io.File");
Constructor<?>[] declaredConstructors = fileClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
//public java.io.File(java.lang.String,java.lang.String)
//public java.io.File(java.lang.String)
//private java.io.File(java.lang.String,java.io.File)
//public java.io.File(java.io.File,java.lang.String)
//public java.io.File(java.net.URI)
//private java.io.File(java.lang.String,int)
}
//指定得到 java.io.File(java.lang.String)
Constructor<?> declaredConstructor = fileClass.getDeclaredConstructor(String.class);
String fileAllPath = "e:\\mynew.txt";
Object file = declaredConstructor.newInstance(fileAllPath); //创建File对象
//file得运行类型就是File
System.out.println(file.getClass());
Method createNewFile = fileClass.getDeclaredMethod("createNewFile");
createNewFile.invoke(file);
System.out.println("创建文件成功" + fileAllPath);
}
}
我亦无他,惟手熟尔