第八章-反射

反射

反射的原理

​ 每一个类都是大Class的一个对象,记录了其属性和方法,在加载类时,存放在class区

​ 每个类的Class对象只有一个

​ 通过Class对象可以用于动态创建不同对象

反射使用
获取Class对象 Class.forName

​ 对象.getclass

​ 类名.class
Class clazz = Class.forName(“全类名”); 点击类名复制 quick copy

​ newInstance(); 直接创建对象,用无参

​ getsuperclass;父类的Class对象 只有一个

​ getInterfaces ; 接口的Class对象 多个

​ getName 全类名

​ getsimplename 类名

​ getpackage 包名

构造方法获取 getConstructor

​ getDeclaredConstructors (); 所有的构造方法

​ c=clazz.getDeclaredConstructor (参数列表 大Class对象); 单个构造方法

​ Constructor c = clazz.getConstructor(String.class,int.class) //表明参数为String的有参构造

创建对象 newInstance

​ Object o = c.newInstance(); 虽然本质是Person类型,但返回的是Object类型

​ Object o = c.newInstance(”zhangsan“,15); 有参构造

​ access 访问 modifies 修饰符 解除私有 c.setAccessiable(true);

变量获取及赋值 getField set

​ getFields 所有public修饰的包括父类的

​ getDeclaredFields 所有变量 不包括父类的

​ getDeclaredField

​ f=clazz.getDeclaredField(变量名)

​ f=clazz.getDeclaredField(“name”)

​ f.set(o,“zhangsan”) //给对象o进行赋值

			f.set(null,14)	//静态变量,可以不用对象
方法获取及调用 method invoke

​ getMethods 所有public修饰的方法 包括父类

​ getDeclaredMethods 本类中所有方法

​ getDeclaredMethod

​ m=clazz.getDeclaredMethod(”方法名“,参数列表 大Class对象)

​ m.invoke(o) //对象o调用无参无返回值的方法m

​ m.invoke(o,12,15) //对象o调用两个int参数的方法m

​ Object o = m.invoke(o,“name”) //对象o调用一个String参数的方法m,返回类型为Object

​ m.invoke(null,12,4); //调用静态方法,参数为两个int,无返回值

public class Test1 {
	public static void main(String[] args) throws Exception {
		Class<?> c = Class.forName("fanshe.User");
		User user = (User) c.newInstance();
		user.setName("han");
		System.out.println(user);

		Constructor<?> con2 = c.getDeclaredConstructor(String.class, int.class);
		User user2 = (User) con2.newInstance("hanyakun", 22);
		System.out.println(user2);

		Constructor<?> con3 = c.getDeclaredConstructor(String.class, int.class, String.class);
		con3.setAccessible(true);
		User user3 = (User) con3.newInstance("gaiku", 99, "nna");
		System.out.println(user3);

		Field[] declaredFields = c.getDeclaredFields();
		Field age = c.getDeclaredField("age");
		age.set(null, 15); // 静态变量,可以不用对象

		Field name = c.getDeclaredField("name");
		name.setAccessible(true);
		Object ob = c.newInstance();
		name.set(ob, "kk");
		System.out.println(ob);

		Method[] declaredMethods = c.getDeclaredMethods();
		Method m = c.getDeclaredMethod("setName", String.class);
		Object invoke = m.invoke(ob, "linghu");
		Method m3 = c.getDeclaredMethod("getName", null);
		Object invoke2 = m3.invoke(ob, null);
		System.out.println(invoke2);
		System.out.println(ob);
		Method m2 = c.getDeclaredMethod("mkoe", null);
		m2.invoke(ob, null);

	}
}

class User {
	private String name;
	static int age = 0;
	private String gender;

	private User(String name, int age, String gender) {
		this.name = name;
		this.age = age;
		this.gender = gender;
	}

	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + ", gender=" + gender + "]";
	}

	public User(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public User() {
		super();
		// TODO Auto-generated constructor stub
	}

	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 String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public void mkoe() {
		System.out.println("这是mkoe 方法");
	}
}
例题

​ 1. 在ArrayList类型中添加整型元素

​ 思考: 范型只对编译有作用,可以使用add() 方法所在类的反射调用add方法,可以躲过编译,

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class Testtttttt {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		ArrayList<String> list = new ArrayList<>();
		list.add("abb");
		Class clazz = list.getClass();
		Method m = clazz.getMethod("add", Object.class);
		m.invoke(list, 1234);
		m.invoke(list, 34);
		System.out.println(list);
	}
}
  1. 通过配置文件解偶合

需求:在子类中将Teacher类升级为SuperTeacher,但不能改动Teacher,因为改动Teacher会对程序进行大的修改,

思考:只需要将Teacher实现接口,在创建Teacher时用反射的方法,使用接口去调用方法,不需要对程序中的类进行更改

import java.io.IOException;
import java.util.Properties;

public class Test {
	public static void main(String[] args) throws Exception {
		//创建properties对象,从配置文件读取对应的全类名
        Properties p = new Properties();
		p.load(Test.class.getClassLoader().getResourceAsStream("config.properties"));
		String property = p.getProperty("tea");
        //得到Class对象,创建对象o;通过转型,得到接口对象,调用Teacher子类的show方法
		Class clazz = Class.forName(property);
		Object o = clazz.newInstance();//o本质为Teacher   即父类引用指向子类对象
		Teachable teach = (Teachable) o;  //将Teacher转型为接口对象,多态,调用子类的方法
                						//不转成teacher对象,是不想对某个类进行修改
		teach.show();
	}
}

interface Teachable {
	void show();
}

class Teacher implements Teachable {
	@Override
	public void show() {
		System.out.println("超级老师,能上天的那种");
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值