黑马程序员_Java的反射机制

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

在java中有一个机制被称之为反射机制,这种机制用于通过class文件对象获取类中的成员变量,构造方法和或者是成员方法。

要获取java的class文件对象又应该通过哪种方式获取呢?

其实获取class文件对象有以下3种方式:

1、Object类的getClass()方法

2、数据类型的静态属性class

3、Class类中的静态方法:public static Class forName(String className)

此外Class中还有三个属性

代码体现:

首先我有一个Person类,还要一个测试类,测试类用于获取Student类中的成员变量、成员方法、和构造方法

package cn.itheima01;

public class Person {
	private String name;
	private int age;
	private String address;
	public Person() {
		super();
	}
	
	private Person(String name) {
		super();
		this.name = name;
	}

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

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

	public void show(){
		System.out.println("show");
	}
	public void method(String s){
		System.out.println("method"+s);
	}
	public String getString(String s,int i){
		return s+"----"+i;
	}
	private void function(){
		System.out.println("function");
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", address=" + address
				+ "]";
	}
	
	
	
	
}
测试类:

package cn.itheima01;

public class ReflectDemo {

	public static void main(String[] args) throws ClassNotFoundException {
		//方式一:
		Person p = new Person();
		Class c = p.getClass();
		
		Person p2 = new Person();
		Class c2 = p2.getClass();
		
		System.out.println(p == p2);
		System.out.println(c==c2);
		
//		方式二
		Class c3 = Person.class;
		System.out.println(c == c3);
		
//		方式三
		Class c4 = Class.forName("cn.itheima01.Person");
		System.out.println(c == c4);
		
	}

}
通过以上三种方式我们获取到了class文件对象

那么我们需要做的是怎样获取构造方法、成员方法和成员变量

需求:我们需要获取Person类中的所有的构造方法,在java中Class类提供了两个方法

public Constructor[] getConstructors():获取所有公共构造方法

public Constructor[] getDeclaredConstructors():获取所有构造方法(包括

package cn.itheima02;

import java.lang.reflect.Constructor;

import cn.itheima01.Person;

public class ReflectDemo {

	public static void main(String[] args) throws Exception{

		Class c = Class.forName("cn.itheima01.Person");
		
		Constructor[] cons = c.getDeclaredConstructors();//拿所有的构造方法
		Constructor[] con = c.getConstructors();
		
		for(Constructor o : cons){
			System.out.println(o);
		}
                for(Constructor o : con){
                        System.out.println(o);
                }
        }

}

既然我们能够获取到所有的构造方法,那么我们能不能获取到单个的构造发方法呢?java也提供了public Constructor getConstructor(Class... parameterTypes)方法去获取单个的构造方法。在以上代码加上下面几行:
                Constructor con = c.getConstructor();
		System.out.println(con);

获取到所有构造方法和和单个方法,我们可以使用newInstance()方法去创建Person类对象实例
                Object o = c.newInstance();
		Person p = (Person)o;
		System.out.println(p);

package cn.itheima02;

import java.lang.reflect.Constructor;

public class ReflectDemo2 {

	public static void main(String[] args) throws Exception{
		
		Class c = Class.forName("cn.itheima01.Person");
		
		Constructor con = c.getConstructor(String.class,int.class,String.class);
		
		Object obj = con.newInstance("小白",18,"莆田");
		
		System.out.println(obj);
		
	}

}

但是如果构造方法被私有化了,我们使用上述方法就会报错,我们可以利用

package cn.itcast_02;

import java.lang.reflect.Constructor;

public class ReflectDemo3 {
	public static void main(String[] args) throws Exception {

		Class c = Class.forName("cn.itcast_01.Person");
		Constructor con = c.getDeclaredConstructor(String.class);

		// 暴力访问
		con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
		Object obj = con.newInstance("小小");

		System.out.println(obj);
  	}
}
我们已经能够获取类中的构造方法并使用了,接下来我们要做的就是如何获取成员变量并且使用。
package cn.itheima03;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class ReflectDemo {

	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
		
		Class c = Class.forName("cn.itheima01.Person");
		Constructor con = c.getConstructor();
		
		Object obj = con.newInstance();
		
		Field addressField = c.getField("address");  //获取公共成员变量
		
		addressField.set(obj,"福建");
		System.out.println(obj);
		
		Field nameField = c.getDeclaredField("name");  //获取私有成员变量
		nameField.setAccessible(true);
		nameField.set(obj, "小白");
		System.out.println(obj);
		
		
	}

}

最后一个就是成员方法的获取并使用,其实通过上面的两个例子我们可以发现所有的都是调用方法,并且是相似的,这样我就不在多说了,直接写一个例子来体现如何获取成员方法并且使用。

package cn.itcast_04;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectDemo {
	public static void main(String[] args) throws Exception {
		// 获取字节码文件对象
		Class c = Class.forName("cn.itcast_01.Person");

		// 获取所有的方法
		// Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法
		// Method[] methods = c.getDeclaredMethods(); // 获取自己的所有的方法
		// for (Method method : methods) {
		// System.out.println(method);
		// }

		Constructor con = c.getConstructor();
		Object obj = con.newInstance();

		/*
		 * Person p = new Person(); p.show();
		 */

		// 获取单个方法并使用
		// public void show()
		// public Method getMethod(String name,Class... parameterTypes)
		// 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
		Method m1 = c.getMethod("show");
		// obj.m1(); // 错误
		// public Object invoke(Object obj,Object... args)
		// 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
		m1.invoke(obj); // 调用obj对象的m1方法

		System.out.println("----------");
		// public void method(String s)
		Method m2 = c.getMethod("method", String.class);
		m2.invoke(obj, "hello");
		System.out.println("----------");

		// public String getString(String s, int i)
		Method m3 = c.getMethod("getString", String.class, int.class);
		Object objString = m3.invoke(obj, "hello", 100);
		System.out.println(objString);
		// String s = (String)m3.invoke(obj, "hello",100);
		// System.out.println(s);
		System.out.println("----------");

		// private void function()
		Method m4 = c.getDeclaredMethod("function");
		m4.setAccessible(true);
		m4.invoke(obj);
	}
}










你可能感兴趣的:(java,移动开发)