一、一个需求引出反射
(一)请看下面的问题
package com.hspedu.reflection.question;
import com.hspedu.Cat;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
@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"));
String classfullpath = properties.get("classfullpath").toString();//com.hspedu.Cat
String methodName = properties.get("method").toString();//hi
System.out.println("classfullpath=" + classfullpath);
System.out.println("method=" + methodName);
//2.创建对象,传统的方法行不通-》反射机制
//3.使用反射机制解决
//(1)加载类,返回Class类型的对象cls
Class cls = Class.forName(classfullpath);
//(2)通过cls通过加载的类 com.hspedu.Cat 的对象实例
Object o = cls.newInstance();
System.out.println("o的运行类型=" + o.getClass());//运行类型
//(3)通过cls得到你加载的类com.hspedu.Cat 的methodName"hi" 的对象方法
// 即:在反射中,可以把方法视为对象(万物皆对象)
Method method1 = cls.getMethod(methodName);
//(4)通过method1 调用方法:即通过方法对象实现调用方法
System.out.println("====================================");
method1.invoke(o);//传统方法 对象.方法(),在反射机制 方法.invoke(对象)
}
}
传统方法 对象.方法(),在反射机制 方法.invoke(对象)
二、反射机制
(一)Java Reflection
(二)Java反射机制原理示意图
(三)Java反射机制可以完成
(四)反射相关的主要类:
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;
public class Reflection01 {
public static void main(String[] args) throws Exception {
//1.使用Properties,可以读写配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.get("classfullpath").toString();//com.hspedu.Cat
String methodName = properties.get("method").toString();//hi
//3.使用反射机制解决
//(1)加载类,返回Class类型的对象cls
Class cls = Class.forName(classfullpath);
//(2)通过cls通过加载的类 com.hspedu.Cat 的对象实例
Object o = cls.newInstance();
System.out.println("o的运行类型=" + o.getClass());//运行类型
//(3)通过cls得到你加载的类com.hspedu.Cat 的methodName"hi" 的对象方法
// 即:在反射中,可以把方法视为对象(万物皆对象)
Method method1 = cls.getMethod(methodName);
//(4)通过method1 调用方法:即通过方法对象实现调用方法
System.out.println("====================================");
method1.invoke(o);//传统方法 对象.方法(),在反射机制 方法.invoke(对象)
//java.lang.reflect.Filed: 代表类的成员变量,Filed对象表示某个类的成员变量
//得到name字段
//getField不能得到私有的属性
Field nameField = cls.getField("age");
System.out.println(nameField.get(o));//传统写法: 对象.成员变量 反射:成员变量对象.get(对象)
//java.lang.reflect.Constructor: 代表类的构造方法,Construction对象表示构造器
Constructor constructor = cls.getConstructor();//()中可以指定构造器参数类型,放回的是无参构造器
System.out.println(constructor);//public com.hspedu.Cat()
Constructor constructor1 = cls.getConstructor(String.class);//传入的String.class就是String类的Class对象
System.out.println(constructor1);//public com.hspedu.Cat(java.lang.String)
}
}
(五)反射优点和缺点
package com.hspedu.reflection;
import com.hspedu.Cat;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//测试反射调用的性能,和优化方案
public class Reflection02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
m1();
m2();
}
//传统方法来调用hi
public static void m1() {
Cat cat = new Cat();
long start = System.currentTimeMillis();
for (int i = 0; i < 90000000; i++) {
cat.hi();
}
long end = System.currentTimeMillis();
System.out.println("传统方法来调用hi 耗时=" + (end - start));//传统方法来调用hi 耗时=2
}
//反射方法调用hi
public static void m2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
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 < 90000000; i++) {
hi.invoke(o);//反射调用方法
}
long end = System.currentTimeMillis();
System.out.println("反射机制来调用hi 耗时=" + (end - start));//反射机制来调用hi 耗时=113
}
}
(六)反射调用优化–关闭访问检查
package com.hspedu.reflection;
import com.hspedu.Cat;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//测试反射调用的性能,和优化方案
public class Reflection02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
m1();
m2();
m3();
}
//传统方法来调用hi
public static void m1() {
Cat cat = new Cat();
long start = System.currentTimeMillis();
for (int i = 0; i < 90000000; i++) {
cat.hi();
}
long end = System.currentTimeMillis();
System.out.println("传统方法来调用hi 耗时=" + (end - start));//传统方法来调用hi 耗时=2
}
//反射方法调用hi
public static void m2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
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 < 90000000; i++) {
hi.invoke(o);//反射调用方法
}
long end = System.currentTimeMillis();
System.out.println("反射机制来调用hi 耗时=" + (end - start));//反射机制来调用hi 耗时=113
}
//反射调用优化 + 关闭访问检测
public static void m3() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
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 < 90000000; i++) {
hi.invoke(o);//反射调用方法
}
long end = System.currentTimeMillis();
System.out.println("setAccessible反射机制来调用hi 耗时=" + (end - start));//setAccessible反射机制来调用hi 耗时=79
}
}
传统方法来调用hi 耗时=3
反射机制来调用hi 耗时=113
setAccessible反射机制来调用hi 耗时=79
三、Class类
(一)基本介绍
package com.hspedu.reflection.class_;
import com.hspedu.Cat;
public class Class01 {
public static void main(String[] args) throws ClassNotFoundException {
//Class类对象不是new出来的,而是系统创建的
//(1)传统new对象
/* ClassLoad
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
* */
//Cat cat = new Cat();
//(2)反射方式,类加载只有一次,要注释上面那一行,Cat cat = new Cat();
/*
ClassLoader类,仍然是通过ClassLoader类加载了Cat类的 Class对象
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
* */
Class cls1 = Class.forName("com.hspedu.Cat");
//3.对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
Class cls2 = Class.forName("com.hspedu.Cat");
System.out.println(cls1.hashCode());//460141958
System.out.println(cls2.hashCode());//460141958
Class cls3 = Class.forName("com.hspedu.Dog");
System.out.println(cls3.hashCode());//1163157884
}
}
(二)Class类的常用方法:
(三)应用案例
package com.hspedu.reflection.class_;
import com.hspedu.Car;
import java.lang.reflect.Field;
//演示Class类的常用方法
public class Class02 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
String classAllPath = "com.hspedu.Car";
//1.获取到Car类 对应的Class对象
//<?>表示不确定的Java类型
Class<?> cls = Class.forName(classAllPath);
//2.输出cls
System.out.println(cls);//显示cls对象,是哪个类的Class对象 class com.hspedu.Car
System.out.println(cls.getClass());//输出真正的运行类型 class java.lang.Class
//3.得到包名
System.out.println(cls.getPackage().getName());//com.hspedu
//4.得到全类名
System.out.println(cls.getName());//com.hspedu.Car
//5.通过cls创建对象实例
//Object o = cls.newInstance();//可以转Car
Car car = (Car)cls.newInstance();
System.out.println(car);//car.toString() //Car{brand='宝马', price=500000, color='白色'}
//6.通过反射获取属性 brand ->Field
Field brand = cls.getField("brand");
System.out.println(brand.get(car));//宝马 私有属性会报错
//7.通过反射给属性赋值
brand.set(car, "奔驰");
System.out.println(brand.get(car));//奔驰
//8.得到所有的属性
System.out.println("=====所有的字段属性=====");
Field[] fields = cls.getFields();
for (Field f: fields) {
System.out.println(f.getName());//brand price color
}
}
}
四、获取Class类对象
(一)演示得到Class对象的各种方式(6)
package com.hspedu.reflection.class_;
import com.hspedu.Car;
/**
*
* 演示得到Class对象的各种方式(6)
* */
public class GetClass_ {
public static void main(String[] args) throws ClassNotFoundException {
//1.Class.forName
String classAllPath = "com.hspedu.Car";//通过读取配置文件获取
Class<?> cls1 = Class.forName(classAllPath);
System.out.println(cls1);
//2.类名.class, 应用场景:用于参数传递
Class cls2 = Car.class;
System.out.println(cls2);
//3.对象.getClass(),应用场景,有对象实例
Car car = new Car();
Class cls3 = car.getClass();
System.out.println(cls3);
//4.通过类加载器【4种】来获取到类的Class对象
ClassLoader classLoader = car.getClass().getClassLoader();
Class cls4 = classLoader.loadClass(classAllPath);
System.out.println(cls4);
//cls1, cls2, cls3, cls4 其实是同一个对象
System.out.println(cls1.hashCode());
System.out.println(cls2.hashCode());
System.out.println(cls3.hashCode());
System.out.println(cls4.hashCode());
//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
//6.基本数据类型对应的包装类,可以通过 .TYPE 得到Class类对象
Class<Integer> type = Integer.TYPE;
Class<Character> type1 = Character.TYPE;
System.out.println(type);//int
System.out.println(integerClass.hashCode());//1163157884
System.out.println(type.hashCode());//1163157884
}
}
五、哪些类型有Class对象
(一)如下类型有Class对象
package com.hspedu.reflection.class_;
import java.io.Serializable;
import java.net.InetAddress;
/**
* 演示哪些类型有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
}
}
六、类加载
(一)基本说明
(二)类加载机制
(三)加载阶段
(四)连接阶段–验证
(五)连接阶段–准备
(六)连接阶段–解析
(七)Initialization(初始化)
package com.hspedu.reflection.classload_;
//演示类加载-初始化阶段
public class ClassLoad03 {
public static void main(String[] args) throws ClassNotFoundException {
//1.加载B类,并生成B的class对象
//2.连接 num = 0
//3.初始化:
// 依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并合并
/*
clinit() {
System.out.println("B 静态代码块被执行");
//num = 300;
num = 100;
}
合并:num = 100
*/
//new B(); //"B() 构造器被执行"
System.out.println(B.num);//如果直接使用类的静态属性,也会导致类的加载
//看看加载类的时候,是有同步机制控制
B b = new B();
}
}
class B {
static {
System.out.println("B 静态代码块被执行");
num = 300;
}
static int num = 100;
public B() {
System.out.println("B() 构造器被执行");
}
}
七、通过反射获取类的结构信息
(一)第一组
package com.hspedu.reflection;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
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();
for (Field field : fields) {
System.out.println("本类即父类的属性" + field.getName());
}
//getDeclaredFields:获取本类中所有的属性
Field[] declaredFields = personCls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本类即父类的属性" + declaredField.getName());
}
//getMethods:获取所有的public修饰器方法,包含本类以及父类的
Method[] methods = personCls.getMethods();
for (Method method : methods) {
System.out.println("本类即父类的方法" + method.getName());
}
//getDeclaredMethods:获取本类中所有的方法
Method[] declaredMethods = personCls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本类中所有的方法=" + declaredMethod.getName());
}
//getConstructors:获取所有public修饰的构造器,包含本类
Constructor<?>[] constructors = personCls.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("本类构造器" + constructor);
}
//getDeclaredConstructors:获取本类中所有构造器
Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println("本类中所有构造器" + declaredConstructor);
}
//getPackage:以Package形式返回 包信息
System.out.println(personCls.getPackage());
//getSuperClass:以Class形式返回父类信息
Class<?> superclass = personCls.getSuperclass();
System.out.println("父类class对象=" + superclass);
//getInterfaces:以Class[] 形式返回接口信息
Class<?>[] interfaces = personCls.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println("接口信息=" + anInterface);
}
//getAnnotations:以Annotation[] 形式注解信息
Annotation[] annotations = personCls.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("注解信息:" + annotation);
}
}
}
interface IA {}
interface IB {}
class A {
public String hobby;
public void hi() {
}
public A() {}
}
@Deprecated
class Person extends A implements IA, IB{
//属性
public String name;
protected int age;
String job;
private double sal;
//构造器
public Person() {}
public Person(String name) {}
//私有构造器
private Person(String name, int age) {}
//方法
public void m1() {
}
protected void m2() {
}
void m3() {
}
private void m4() {
}
}
com.hspedu.reflection.Person
Person
本类即父类的属性name
本类即父类的属性hobby
本类即父类的属性name
本类即父类的属性age
本类即父类的属性job
本类即父类的属性sal
本类即父类的方法m1
本类即父类的方法hi
本类即父类的方法wait
本类即父类的方法wait
本类即父类的方法wait
本类即父类的方法equals
本类即父类的方法toString
本类即父类的方法hashCode
本类即父类的方法getClass
本类即父类的方法notify
本类即父类的方法notifyAll
本类中所有的方法=m1
本类中所有的方法=m2
本类中所有的方法=m4
本类中所有的方法=m3
本类构造器public com.hspedu.reflection.Person(java.lang.String)
本类构造器public com.hspedu.reflection.Person()
本类中所有构造器private com.hspedu.reflection.Person(java.lang.String,int)
本类中所有构造器public com.hspedu.reflection.Person(java.lang.String)
本类中所有构造器public com.hspedu.reflection.Person()
package com.hspedu.reflection
父类class对象=class com.hspedu.reflection.A
接口信息=interface com.hspedu.reflection.IA
接口信息=interface com.hspedu.reflection.IB
注解信息:@java.lang.Deprecated()
(二)第二组
package com.hspedu.reflection;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectionUtils {
public static void main(String[] args) {
}
@Test
public void api_02() throws ClassNotFoundException {
//得到Class对象
Class<?> personCls = Class.forName("com.hspedu.reflection.Person");
//getDeclaredFields:获取本类中所有的属性
Field[] declaredFields = personCls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本类即父类的属性" + declaredField.getName()
+ " 该属性的修饰符值=" + declaredField.getModifiers()
+ " 该属性的类型=" + declaredField.getType());
}
}
}
interface IA {}
interface IB {}
class A {
public String hobby;
public void hi() {
}
public A() {}
}
@Deprecated
class Person extends A implements IA, IB{
//属性
public String name;
protected static int age;//4 + 8
String job;
private double sal;
//构造器
public Person() {}
public Person(String name) {}
//私有构造器
private Person(String name, int age) {}
//方法
public void m1() {
}
protected void m2() {
}
void m3() {
}
private void m4() {
}
}
本类即父类的属性name 该属性的修饰符值=1 该属性的类型=class java.lang.String
本类即父类的属性age 该属性的修饰符值=12 该属性的类型=int
本类即父类的属性job 该属性的修饰符值=0 该属性的类型=class java.lang.String
本类即父类的属性sal 该属性的修饰符值=2 该属性的类型=double
(三)第三组
package com.hspedu.reflection;
import org.junit.Test;
import java.lang.reflect.Method;
public class ReflectionUtils {
public static void main(String[] args) {
}
@Test
public void api_02() throws ClassNotFoundException {
Class<?> personCls = Class.forName("com.hspedu.reflection.Person");
//getDeclaredMethods:获取本类中所有的方法
Method[] declaredMethods = personCls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本类中所有的方法=" + declaredMethod.getName()
+ " 该方法的访问修饰符值=" + declaredMethod.getModifiers()
+ " 该方法返回类型" + declaredMethod.getReturnType());
//输出当前这个方法的形参数组情况
System.out.println("========分组线============");
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("该方法形参类型=" + parameterType);
}
}
}
}
interface IA {}
interface IB {}
class A {
public String hobby;
public void hi() {
}
public A() {}
}
@Deprecated
class Person extends A implements IA, IB{
//属性
public String name;
protected static int age;//4 + 8
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() {
}
}
本类中所有的方法=m1 该方法的访问修饰符值=1 该方法返回类型void
分组线====
该方法形参类型=class java.lang.String
该方法形参类型=int
该方法形参类型=double
本类中所有的方法=m2 该方法的访问修饰符值=4 该方法返回类型class java.lang.String
分组线====
本类中所有的方法=m4 该方法的访问修饰符值=2 该方法返回类型void
分组线====
本类中所有的方法=m3 该方法的访问
(四)第四组
package com.hspedu.reflection;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ReflectionUtils {
public static void main(String[] args) {
}
@Test
public void api_02() throws ClassNotFoundException {
Class<?> personCls = Class.forName("com.hspedu.reflection.Person");
//getDeclaredMethods:获取本类中所有的方法
Method[] declaredMethods = personCls.getDeclaredMethods();
//getDeclaredConstructors:获取本类中所有构造器
Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println("===============");
System.out.println("本类中所有构造器" + declaredConstructor);
Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("该构造器的形参类型:" + parameterType);
}
}
}
}
interface IA {}
interface IB {}
class A {
public String hobby;
public void hi() {
}
public A() {}
}
@Deprecated
class Person extends A implements IA, IB{
//属性
public String name;
protected static int age;//4 + 8
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() {
}
}
===============
本类中所有构造器private com.hspedu.reflection.Person(java.lang.String,int)
该构造器的形参类型:class java.lang.String
该构造器的形参类型:int
===============
本类中所有构造器public com.hspedu.reflection.Person(java.lang.String)
该构造器的形参类型:class java.lang.String
===============
本类中所有构造器public com.hspedu.reflection.Person()
八、通过反射创建对象
(一)案例演示
package com.hspedu.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//演示通过反射机制创建实例
public class ReflecCreateInstance {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//1.先获取到User类的Class对象
Class<?> userClass = Class.forName("com.hspedu.reflection.User");
//2.通过public 的无参构造器创建实例
Object o = userClass.newInstance();
System.out.println(o);
//3.通过public 的有参构造器创建实例
/*
constructor 对象就是
public User(String name) {
this.name = name;
}
*/
//3.1 先得到对应构造器
Constructor<?> constructor = userClass.getConstructor(String.class);
//3.2 创建实例,并传入实参
Object mary = constructor.newInstance("mary");
System.out.println("mary=" + mary);
//4.通过非public 的有参构造器创建实例
//4.1得到private的构造器
Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
//4.2创建实例
constructor1.setAccessible(true);//暴破【暴力破解】,使用反射,可以范文private构造器/方法/属性,反射面前,都是纸老虎
Object user2 = constructor1.newInstance(100, " 张三丰");
System.out.println("user2=" + user2);
}
}
class User { //User类
private int age = 10;
private String name = "jack";
public User() {}//无参public
public User(String name) {
this.name = name;
}
private User(int age, String name) {//private 有参构造器
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
User{age=10, name='jack'}
mary=User{age=10, name='mary'}
user2=User{age=100, name=' 张三丰'}
九、通过反射访问类中的成员
(一)访问属性
package com.hspedu.reflection;
import java.lang.reflect.Field;
//演示反射操作属性
public class ReflecAccessProperty {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
//1.得到Student类对应的Class对象
Class<?> stuClass = Class.forName("com.hspedu.reflection.Student");
//2.创建对象
Object o = stuClass.newInstance();//o 的运行类型就是Student
System.out.println(o.getClass());//Student
//3.使用反射得到age属性对象
Field age = stuClass.getField("age");
age.set(o, 88);//通过反射来操作属性
System.out.println(o);//88
System.out.println(age.get(o));//88
//4.使用反射操作name属性
Field name = stuClass.getDeclaredField("name");
//对name进行暴破
name.setAccessible(true);
//name.set(o, "jack");
name.set(null, "jack");//因为name是static属性,因此o也可以写出null
System.out.println(o);
System.out.println(name.get(o));//获取属性值
System.out.println(name.get(null));//获取属性值
}
}
class Student {
public int age;
private static String name;
public Student() {
}
@Override
public String toString() {
return "Student{" +
"age=" + age + " name=" + name+
'}';
}
}
class com.hspedu.reflection.Student
Student{age=88 name=null}
88
Student{age=88 name=jack}
jack
jack
(二)访问方法
package com.hspedu.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//通过反射调用方法
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 hi1 = bossCls.getDeclaredMethod("hi", String.class);
//3.2调用
hi1.invoke(o, "jack");
//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, 100, "张三", '男'));
//4.3因为say方法是static的,还可以这样调用
System.out.println(say.invoke(null, 200, "李四" ,'女'));
//5.在反射中,如果方法有返回值,统一返回Object,但是运行类型和方法定义的返回类型一致
Object reVal = say.invoke(null, 300, "万五", '男');
System.out.println("reVal 的运行类型=" + reVal.getClass());//String
}
}
class Boss {
public int age;
private static String name;
public Boss() {
}
private static String say(int n, String s, char c) {
return n + " " + s + " " + c;
}
public void hi(String s) {
System.out.println("hi " + s);
}
}
hi jack
100 张三 男
200 李四 女
reVal 的运行类型=class java.lang.String