1. 反射创建对象 725
1.方式一: 调用类中的public修饰的无参构造器
2.方式二:调用类中的指定构造器
3. Class类相关方法
newInstance :调用类中的无参构造器,获取对应类的对象
getConstructor(as.clazz):根据参数列表,获取对应的public构造器对象
getDecalaredConstructor(Class..clazz):根据参数列表,获取对应的所有构造器对象
4. Constructor类相关方法
setAccessible:暴破
newInstance(Object..obj):调用构造器
1.1 案例演示 725
测试 1:通过反射创建某类的对象,要求该类中必须有 public 的无参构造
测试 2:通过调用某个特定构造器的方式,实现创建某类的对象
代码在com.stulzl.reflection_create_instance包中
ReflectionCreateInstance
package com.stulzl.reflection_create_instance;
import jdk.nashorn.internal.ir.CallNode;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//反射创建对象 725
//测试 1:通过反射创建某类的对象,要求该类中必须有 public 的无参构造
//测试 2:通过调用某个特定构造器的方式,实现创建某类的对象
public class ReflectionCreateInstance {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//1.先获取User的Class对象
Class userClass = Class.forName("com.stulzl.reflection_create_instance.User");
//2.通过public的无参构造器创建实例
Object o = userClass.newInstance();
System.out.println(o);//User [age=10, name=中国]
//3.通过public的有参构造器创建实例
/*
constructor 对象就是
public User(String name) {//public 的有参构造器
this.name = name;
}
*/
//先得到对应的构造器
Constructor constructor = userClass.getConstructor(String.class);
//再创建实例,传入实参
Object china = constructor.newInstance("China");
System.out.println("China="+china);
//4.通过非public的有参构造器创建实例
//得到对应的private构造器
Constructor constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
//创建实例,传入参数
constructor1.setAccessible(true);//爆破,使用反射可以访问private构造器
Object user2 = constructor1.newInstance(100, "世界");
System.out.println("user2="+user2);
}
}
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 + "]";
}
}
2. 通过反射访问类中的成员 726
2.1 访问属性
1.根据属性名获取Field对象
Field f = clazz对象.getDeclaredField(属性名);
2. 暴破: f.setAccessible(true); //f是Field
3.访问
f.set(o,值); // o 表示对象
syso(f.get(o))// o 表示对象
4. 注意:如果是静态属性,则set和get中的参数o,可以写成null
2.2 案例演示 726
代码在com.stulzl.reflection_access_property包中
ReflectionAccessProperty
package com.stulzl.reflection_access_property;
import java.lang.reflect.Field;
//通过反射访问类中的成员 访问属性 726
public class ReflectionAccessProperty {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
//得到Student类对应的Class对象
Class stuClass = Class.forName("com.stulzl.reflection_access_property.Student");
//2.创建对象
Object o = stuClass.newInstance();
System.out.println(o.getClass());//运行类型Student
//3.使用反射得到age属性对象
Field age = stuClass.getField("age");
age.set(o,88);
System.out.println(o);//Student [age=88, name=null]
//也可以这样返回
System.out.println(age.get(o));//88
//4.使用反射操作name属性
Field name = stuClass.getDeclaredField("name");
//因为name是私有属性,访问时要爆破,爆破后可以操作private属性
name.setAccessible(true);
//第一种写法
//name.set(o,"中国");
//第二种写法
name.set(null,"世界");;//因为 name 是 static 属性,因此 o 也可以写出 null
System.out.println(o);
System.out.println(name.get(o));
System.out.println(name.get(null));//写null,获取属性值时, 要求 name 是 static
}
}
class Student {//类
public int age;
private static String name;
public Student() {//构造器
}
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
}
2.3 访问方法 727
1.根据方法名和参数列表获取Method方法对象:
Method m = clazz.getDeclaredMethod(方法名,xx.class); //得到本类的所有方法
2.获取对象: Object o= clazz.newlnstance;
3.暴破: m.setAccessible(true);
4.访问: Object returnValue = m.invoke(o,实参列表);//o就是对象
5.注意:如果是静态方法,则invoke的参数o,可以写成null!
2.4 案例演示 727
代码在com.stulzl.reflection_access_method包中
ReflectionAccessMethod
package com.stulzl.reflection_access_method;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//通过反射访问类中的成员 访问方法 727
public class ReflectionAccessMethod {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//得到Boss对应的Class对象
Class bossClass = Class.forName("com.stulzl.reflection_access_method.Boss");
//创建对象
Object o = bossClass.newInstance();
//得到public的hi()方法
Method hi = bossClass.getMethod("hi",String.class);
//还可以这样写
//Method hi = bossClass.getDeclaredMethod("hi", String.class);
//调用
hi.invoke(o, "中国");
//得到private的say()方法
Method say = bossClass.getDeclaredMethod("say",int.class,String.class, char.class);
say.setAccessible(true);//因为say()方法时私有的所以要爆破
System.out.println(say.invoke(o,100,"张三",'男'));
// 因为 say 方法是 static 的,还可以这样调用 ,可以传入 null
System.out.println(say.invoke(null,200,"李四",'男'));
//在反射中,如果方法有返回值,统一返回 Object 但是他运行类型和方法定义的返回类型一致
Object reVal = say.invoke(null, 300,"王五", '男');
System.out.println("运行类型="+reVal.getClass());//String
System.out.println(reVal);
}
}
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) {//普通 public 方法
System.out.println("hi " + s);
}
}
3. 练习1 728
通过反射修改私有成员变量
1. 定义PrivateTest类, 有私有name属性,并且属性值为hellokitty
2.提供getName的公有方法
3. 创建PrivateTest的类, 利用Class类得到私有的name属性,修改私有的name属性值,
并调用getName()的方法打印name属性值
代码在com.stulzl.exercise01包中
Exercise01
package com.stulzl.exercise01;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//本站练习01 728
//通过反射修改私有成员变量
//1. 定义PrivateTest类, 有私有name属性,并且属性值为hellokitty
//2.提供getName的公有方法
//3. 创建PrivateTest的类, 利用Class类得到私有的name属性,修改私有的name属性值,
//并调用getName()的方法打印name属性值
public class Exercise01 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
//1. 得到PrivateTest类的Class对象
Class privateTestClass = PrivateTest.class;
//创建对象实例
PrivateTest privateTestObj = privateTestClass.newInstance();
//因为name是私有的所以用getDeclaredField,并且需要爆破才能修改值
Field name = privateTestClass.getDeclaredField("name");
//爆破
name.setAccessible(true);
name.set(privateTestObj,"天龙八部");
//得到getName()方法对象
Method getName = privateTestClass.getMethod("getName");
Object invoke = getName.invoke(privateTestObj);//接收返回值
System.out.println("name属性的值="+invoke);//输出//name属性的值=天龙八部
}
}
class PrivateTest {
private String name = "hellokitty";
public String getName() {
return name;
}
}
4. 练习2 728
利用反射和File完成以下功能Homework02.java
1.利用Class类的forName方法得到File类的class对象
2.在控制台打印File类的所有构造器
3.通过newInstance的方法创建File对象, 并创建E:\mynew.txt文件
提示:创建文件的正常写法如下:
File file = new File(" d:\\aa.txt")://内存
file.createNewFile();//方法,才能真正的创建文件
代码在com.stulzl.exercise02包中
Exercise02
package com.stulzl.exercise02;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//本章练习02 728
//利用反射和File完成以下功能Homework02.java
//1.利用Class类的forName方法得到File类的class对象
//2.在控制台打印File类的所有构造器
//3.通过newInstance的方法创建File对象, 并创建E:\mynew.txt文件
//提示:创建文件的正常写法如下:
//File file = new File(" d:\\aa.txt")://内存
//file.createNewFile();//方法,才能真正的创建文件
public class Exercise02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//利用Class类的forName方法得到File类的class对象
Class fileClass = Class.forName("java.io.File");
//得到所有构造器
Constructor[] declaredConstructors = fileClass.getDeclaredConstructors();
//遍历输出
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println("File构造器="+declaredConstructor);
}
//指定得到 这个File构造器=public 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 = new File(" d:\\aa.txt")://内存
//file.createNewFile();//方法,才能真正的创建文件
//得到createNewFile()方法对象
Method createNewFile = fileClass.getMethod("createNewFile");
createNewFile.invoke(file);//真正的创建文件了
//file的运行类型就是File
System.out.println(file.getClass());
System.out.println("创建文件成功"+fileAllPath);
}
}