[黑马程序员]--反射

------- android培训java培训、期待与您交流! ----------

1,概述

    要想对一个类进行解剖,就必须先获取到该类的字节码文件对象。
    其实也就是要获取到字节码文件对象的描述类Class。
 
    那么,我们有几种方式获取到一个class文件的Class对象呢?
    1:通过对象的getClass()方法获取
    2:任意类型的都有一个静态class属性
   3:通过Class类的一个forName(String className)静态方法返回一个Class对象
       className必须是全路径名称。也就是如果有包,必须带包名。
  
   一般来说,如果自己写案例,用前两种都是可以的。
   但是,开发中一般使用第三种。为什么呢?
   因为第三种方式接受的是一个字符串路径,将来可以通过配置文件获取,通用性好。

|--常见的获取反射类的方法总结

程序如下:

public class ReflectDemo {
	public static void main(String[] args) throws ClassNotFoundException {
		// 方式1
		Person p = new Person();
		Class c = p.getClass();

		Person p2 = new Person();
		Class c2 = p2.getClass();

		System.out.println(p == p2);// false
		System.out.println(c == c2);// true

		// 方式2
		Class c3 = Person.class;
		System.out.println(c == c3);// true
		
		// 方式3
		Class c4 = Class.forName("cn.itcast_01.Person");
		System.out.println(c == c4);// true
	}
}
class Person {
	private String name;
	int age;
	public String address;

	public Person() {
	}

	Person(String name) {
		this.name = name;
	}

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

	public void show() {
		System.out.println("show");
	}

	public void method(String name) {
		System.out.println("show " + name);
	}

	public String function(String name, int age) {
		return name + "***" + age + "***" + "function";
	}

	private void hello() {
		System.out.println("hello");
	}

	@Override
	public String toString() {
		return name + "***" + age;
	}
}

2,通过反射获取构造方法

|--历程1

程序如下:

public class ReflectDemo {
	public static void main(String[] args) throws ClassNotFoundException,
			NoSuchMethodException, SecurityException, InstantiationException,
			IllegalAccessException, IllegalArgumentException,
			InvocationTargetException {
		// 获取字节码文件对象
		Class c = Class.forName("cn.itcast_01.Person");

		// 获取构造方法
		// public Constructor[] getConstructors() 所有公共构造方法
		// Constructor[] cons = c.getConstructors();
		// public Constructor[] getDeclaredConstructors() 所有构造方法
		Constructor[] cons = c.getDeclaredConstructors();
		for (Constructor con : cons) {
			System.out.println(con);
		}
		System.out.println("**************************************");
		// 获取单个的构造方法对象
		// public Constructor getConstructor(Class... parameterTypes)
		// 参数指的是你的构造方法的形式参数的classe类型
		Constructor con = c.getConstructor();
		// System.out.println(con);

		/*
		 * Person p = new Person(); System.out.println(p);//null***0
		 */
		// 通过反射获取到的构造方法对象创建对象
		// public Object newInstance(Object... initargs)
		// 这里指的是实际传递的参数
		Object obj = con.newInstance();
		System.out.println(obj);
		
//		Person p = (Person)obj;
//		p.show();
		
		System.out.println("**************************************");
		/*
		 * Person p = new Person("林青霞",28);
		 * System.out.println(p); //林青霞***28
		 */
		Class[] classes = new Class[2];
		classes[0] = String.class;
		classes[1] = int.class;
		Constructor con2 = c.getConstructor(classes);
		//System.out.println(con2);
		
		//通过带参数构造器创建对象
		Object[] objs = new Object[2];
		objs[0] = "林青霞";
		objs[1] = 28;
		Object obj2 = con2.newInstance(objs);
		System.out.println(obj2);

	}
}

|--历程2

程序如下:

public class ReflectDemo2 {
	public static void main(String[] args) throws ClassNotFoundException,
			NoSuchMethodException, SecurityException, InstantiationException,
			IllegalAccessException, IllegalArgumentException,
			InvocationTargetException {
		// 获取Class文件对象
		Class c = Class.forName("cn.itcast_01.Person");

		// 获取带两个参数的构造方法
		// Class[] classes = new Class[2];
		// classes[0] = String.class;
		// classes[1] = int.class;
		// Constructor con = c.getConstructor(classes);
		// Constructor con = c.getConstructor(new Class[] { String.class,
		// int.class });
		Constructor con = c.getConstructor(String.class, int.class);

		// Object[] objs = new Object[2];
		// objs[0] = "林青霞";
		// objs[1] = 28;
		// Object obj = con.newInstance(objs);
		// Object obj = con.newInstance(new Object[] { "林青霞", 28 });
		Object obj = con.newInstance("林青霞", 28);
		System.out.println(obj);
	}
}

3, 通过反射获取成员变量

|--历程

程序如下:

 public class ReflectDemo {
	public static void main(String[] args) throws ClassNotFoundException,
			NoSuchFieldException, SecurityException, NoSuchMethodException,
			InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		// 获取字节码文件对象
		Class c = Class.forName("cn.itcast_01.Person");

		// 获取成员变量
		// public Field[] getFields() 获取公共的成员变量
		// Field[] fields = c.getFields();
		// public Field[] getDeclaredFields() 获取成员变量
		Field[] fields = c.getDeclaredFields();
		for (Field f : fields) {
			System.out.println(f);
		}

		System.out.println("************************************");
		// 单个获取
		// public Field getField(String name)
		// Field f = c.getField("address");
		// public Field getDeclaredField(String name)
		Field f = c.getDeclaredField("name");

		// System.out.println(f);

		// 获取无参数构造方法
		Constructor con = c.getConstructor();
		Object obj = con.newInstance();

		// public void set(Object obj,Object value)
		// obj其实就是对象,value就是值
		// public void setAccessible(boolean flag) 暴力访问
		f.setAccessible(true);
		f.set(obj, "林青霞");
		// 私有的成员变量和方法不能直接被使用。

		System.out.println(obj);

	}
}

4,通过反射获取成员属性

|--历程

程序如下:

public class ReflectDemo {
	public static void main(String[] args) throws ClassNotFoundException,
			NoSuchMethodException, SecurityException, InstantiationException,
			IllegalAccessException, IllegalArgumentException,
			InvocationTargetException {
		// 获取字节码文件对象
		Class c = Class.forName("cn.itcast_01.Person");

		// public Method[] getMethods() 获取所有的本身及其父类的公共方法
		// Method[] methods = c.getMethods();
		// public Method[] getDeclaredMethods() 获取本类的所有方法
		Method[] methods = c.getDeclaredMethods();
		for (Method m : methods) {
			System.out.println(m);
		}

		System.out.println("****************************************");
		// 通过无参构造创建一个对象
		Constructor con = c.getConstructor();
		Object obj = con.newInstance();

		// 获取单个的方法
		// public Method getMethod(String name,Class... parameterTypes)
		// 第一个是方法名称,第二个是参数的class类型
		Method m = c.getMethod("show");

		/*
		 * Person p = new Person(); p.show();
		 */
		// public Object invoke(Object obj,Object... args)
		// Object表示返回值类型,obj表示是哪个对象调用方法,args是实际传递的参数
		m.invoke(obj);
		System.out.println("****************************************");
		Method m2 = c.getMethod("method", String.class);
		m2.invoke(obj, "周星驰");
		
		System.out.println("****************************************");
		Method m3 = c.getMethod("function", String.class,int.class);
		Object oo = m3.invoke(obj, "周润发",55);
		System.out.println(oo);
		
		System.out.println("****************************************");
		Method m4 = c.getDeclaredMethod("hello");
		m4.setAccessible(true);
		m4.invoke(obj);
	}
}

5,两个应用历程

|--在ArrayList<Integer>中写String

程序如下:

public class ArrayListTest {
	public static void main(String[] args) throws NoSuchMethodException,
			SecurityException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		ArrayList<Integer> array = new ArrayList<Integer>();

		// array.add(10);
		// array.add("hello");

		Class c = array.getClass();
		Method m = c.getMethod("add", Object.class);
		m.invoke(array, "hello");
		m.invoke(array, "world");

		System.out.println(array);
	}
}

|-- 配置文件

程序如下:

public class Test {
	public static void main(String[] args) throws Exception {
		// Student s = new Student();
		// s.study();
		// Teacher t = new Teacher();
		// t.study();

		// 用反射实现
		/*
		 * 配置文件的键应该是已知的 className methodName
		 */
		Properties prop = new Properties();
		FileReader fr = new FileReader("person.txt");
		prop.load(fr);
		fr.close();

		String className = prop.getProperty("className");
		String mehodName = prop.getProperty("methodName");

		// 获取字节码文件对象
		Class c = Class.forName(className);

		// 创建对象
		Constructor con = c.getConstructor();
		Object obj = con.newInstance();

		// 获取方法
		Method m = c.getMethod(mehodName);

		m.invoke(obj);
	}
}

class Teacher {
	public void study() {
		System.out.println("老师也得学习");
	}
}

class Student {
	public void study() {
		System.out.println("学生爱学习");
	}
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值