一、使用反射解决读取配置文件的问题
作用:可以在不修改源代码的基础上就可以实现功能,很牛啊 案例1
(1)在src下新建配置文件 re.properties
classfullpath=com.hspedu.Cat
method=hi
(2)在src下新建com.hspedu包下新建Cat类
package com.hspedu;
public class Cat {
private String name = "招财猫";
public void hi(){
System.out.println("hi"+name);
}
}
(3)主方法
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
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();//"com.hspedu.Cat
String methods = properties.get("method").toString();//hi
// System.out.println(classfullpath+methods);
//3.使用反射机制解决
//(1)加载类,返回Class类型对象 cls
Class<?> cls = Class.forName(classfullpath);
//(2)通过 cls 得到你加载的类 com.hspedu.Cat的对象实例
Object o = cls.newInstance();
System.out.println("运行类型:"+o.getClass()); //运行类型
//(3)通过cls得到你加载类的method的methodName 的方法对象 在反射中 可以把方法看为对象
Method method1 = cls.getMethod(methods);
//(4)通过method1调用方法,即通过方法对象来实现调用方法
method1.invoke(o);//传统方法 对象.方法() , 反射机制 方法.invoke(对象)
}
}
二、反射机制
(1)反射机制
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时得到任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的成员变量和方法
- 生成动态代理
(2)反射相关的主要类
- java.lang.Class:代表一个类
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Filed:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造方法
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
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();//"com.hspedu.Cat
String methods = 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.getClass()); //运行类型
//(3)通过cls得到你加载类的method的methodName 的方法对象 在反射中 可以把方法看为对象
Method method1 = cls.getMethod(methods);
//(4)通过method1调用方法,即通过方法对象来实现调用方法
method1.invoke(o);//传统方法 对象.方法() , 反射机制 方法.invoke(对象)
//得到name字段
Field name = cls.getField("name");//getFild不能获取私有属性
System.out.println(name.get(o)); //传统写法 对象.成员变量 反射 : 成员变量对象.get(对象)
//获取构造器
Constructor<?> constructor = cls.getConstructor(); //()可以指定构造器
System.out.println(constructor);
}
}
三、反射调用方法的优化
hi.setAccessible(true); //在反射调用方法时,取消访问检查
//(3)通过cls得到你加载类的method的methodName 的方法对象 在反射中 可以把方法看为对象
Method method1 = cls.getMethod(methods);
method1.setAccessible(true);
四、Class类常用的方法
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) throws Exception{
String classAllPath = "com.hspedu.Cat";
//获取Cat类 对应 的Class对象
//<?> 表示不确定Java类型
Class<?> cls = Class.forName(classAllPath);
//输出cls
System.out.println(cls.getClass());//获取运行类型
//获取包名
System.out.println(cls.getPackage().getName());
//获取类名
System.out.println(cls.getName());
//通过cls创建对象实例
Object o = cls.newInstance();
//获取成员 私有属性会报错的
Field name = cls.getField("name");
System.out.println(name.get(o)); //反射原理
//通过反射给属性设置值
name.set(o,"汤姆猫");
System.out.println(name.get(o));
}
}
五、反射实例
(1)反射爆破创建实例:
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) throws Exception{
//1.先获取到User类的Class
Class<?> userClass = Class.forName("com.hspedu.User");
//2.通过public的无参构造器创建实例
Object o = userClass.newInstance();
System.out.println(o);
//3.通过public的有参构造器创建实例
//3.1.先得到构造器
Constructor<?> constructor = userClass.getConstructor(int.class);
//3.2 创建实例
Object hsp = constructor.newInstance(19);
System.out.println(hsp);
//4.通过private的有参构造器创建实例
//4.1.先得到构造器
Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
//4.2 创建实例
constructor1.setAccessible(true); //爆破 使用反射可以访问私有(private)构造器
Object zsf = constructor1.newInstance(100, "张三丰");
System.out.println(zsf);
}
}
package com.hspedu;
public class User {
private int age = 10;
private String name = "张三";
public User() {
}
public User(int age) {
this.age = age;
}
private User(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
(2)反射爆破操作属性:
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) throws Exception{
//1.先获取到User类的Class
Class<?> userClass = Class.forName("com.hspedu.User");
//2.创建对象
Object o = userClass.newInstance();
System.out.println(o.getClass());
//3.使用反射得到age属性对象
Field age = userClass.getField("age");
age.set(o,88);
System.out.println(age.get(o));//返回属性值
//使用反射操作name属性
Field name = userClass.getDeclaredField("name");
//对name进行爆破,可以操作private属性
name.setAccessible(true);
name.set(o,"老韩");
System.out.println(o);
}
}
package com.hspedu;
public class User {
public int age;
private static String name;
public User() {
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
(3)使用反射获取方法:
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) throws Exception {
//1.先获取到User类的Class
Class<?> userClass = Class.forName("com.hspedu.User");
//2.创建对象
Object o = userClass.newInstance();
//3.调用public的hi方法
// Method h1 = userClass.getMethod("hi",String.class); //获取public
Method h1 = userClass.getDeclaredMethod("hi", String.class);//获取全部方法包括私有
//3.2调用
h1.invoke(o, "韩顺平教育");
//4.调用private static 方法
//4.得到say 方法对象
Method say = userClass.getDeclaredMethod("say", int.class, String.class, char.class);
//私有方法所以我们需要爆破一下
say.setAccessible(true);
Object invoke = say.invoke(o, 12, "张三", 'A');
System.out.println(invoke);
}
}
package com.hspedu;
public class User {
public int age;
private static String name;
public User() {
}
private static String say(int n, String s, char c) {
return n + " " + s + " " + c;
}
public void hi(String s) {
System.out.println("hi " + s);
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
六、课后作业
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
public static void main(String[] args) throws Exception {
//1.先获取到User类的Class
Class<?> userClass = Class.forName("com.hspedu.User");
//2.创建对象
Object o = userClass.newInstance();
Field name = userClass.getDeclaredField("name");
name.setAccessible(true); //爆破啊
System.out.println(name.get(o)); //获取未修改前
name.set(o,"韩老师");
Method getName = userClass.getMethod("getName");
System.out.println(getName.invoke(o));
}
}
package com.hspedu;
public class User {
private String name = "hellokitty";
public String getName() {
return name;
}
}