【我的Java笔记】Java反射

Java反射

1.反射的概念:

Java的反射机制是在运行状态中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。这种动态获取的信息以及动态调用对象的方法的功能成为Java语言的反射机制。


获取该类的字节码文件对象——>class类对象(通过class类对象获取该类里的一些属性<成员变量,构造方法,成员方法>)


2.获取类的字节码文件对象的三种方法

(1)Object类中的getClass() 方法此方法表示正在运行的类:Class类

(2)数据类型的class属性(例如String.class,Student.class)

       *(3)Class类中的特有方法:forName(String className)获取字节码文件对象 

注:此种方法内的参数className为类的全路径名称


class类

1.成员方法:

(1)public static Class forName(String className)返回字类的节码文件对象


(2)获取构造器

 ①public Constructor getConstructor(Class... parameterTypes)

返回一个Constructor对象,此 Class 对象所表示的类的指定公共构造方法(只可访问公共构造方法
 ②public Constructor[] getConstructors()

返回一个Constructor对象,这些对象反映此 Class 对象所表示的类的所有公共构造方法
 ③ public Constructor getDeclaredConstructor(Class... parameterTypes)

该对象反映此 Class 对象所表示的类或接口的指定构造方法(包括私有

注:此方法可访问私有构造方法,但需加上Constructor类中的setAccessible(true) 方法,取消Java语言访问检查
 ④public Constructor[] getDeclaredConstructors()

这些对象反映此 Class 对象表示的类声明的所有构造方法(包括私有


(3)获取成员变量

①public Field getField(String name)

它反映此 Class 对象所表示的类或接口的指定公共成员字段
②public Field[] getFields() 

这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
③public Field getDeclaredField(String name) 

该对象反映此 Class 对象所表示的类或接口的指定已声明字段(包括私有
④public Field[] getDeclaredFields() 

这些对象反映此 Class 对象所表示的类或接口所声明的所有字段(包括私有


(4)获取成员方法

①public Method getMethod(String name,Class... parameterTypes)
它反映此 Class 对象所表示的类或接口的指定公共成员方法
②public Method[] getMethods()
这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的 那些的类或接口)的公共 member 方法

注:该方法会返回此类的所有方法,包括继承的方法
③public Method getDeclaredMethod(String name,Class... parameterTypes)
该对象反映此 Class 对象所表示的类或接口的指定已声明方法(此方法可获取单个私有方法
④public Method[] getDeclaredMethods()
这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方 法,但不包括继承的方法

注:此方法返回此类的所有方法,但不包括继承的方法





访问构造方法

1.getConstructor(Class... parameterTypes)

2.getConstructors()

3.getDeclaredConstructor(Class... parameterTypes)

4.getDeclaredConstructors()


步骤:

(1)通过forName() 方法获取类的字节码文件对象Class c

(2)通过getConstructor() 方法获取构造器Constructor对象

(3)通过Constructor 的newInstance() 方法创建类的实例Object obj


注:setAccessible(true)方法可以取消Java语言访问检查(可以访问私有构造方法)






访问成员变量

1.getField(String name)

2.getFields()

3.getDeclaredField(String name)

4.getDeclaredFields()


步骤:

(1)通过forName() 方法获取类的字节码文件对象Class c

(2)通过getConstructor() 方法获取构造器Constructor对象

(3)通过Constructor 的newInstance() 方法创建类的实例Object obj

需先创建构造器实例

(4)通过Constructor 的getField()方法获取Field对象

(5)通过Field 中的set(Object obj, Object value)方法给成员变量设置值


注:setAccessible(true)方法可以取消Java语言访问检查(可以访问私有成员变量)







访问成员方法

1.getMethod(String name,Class... parameterTypes)

2.getMethods()

3.getDeclaredMethod(String name,Class... parameterTypes)

4.getDeclaredMethods()


步骤:

(1)通过forName() 方法获取类的字节码文件对象Class c

(2)通过getConstructor() 方法获取构造器Constructor对象

(3)通过Constructor 的newInstance() 方法创建类的实例Object obj

需先创建构造器实例

(4)通过 Constructor 中的getMethod(String name,Class... parameterTypes)方法获取Method对象

(5)通过Method 中的public Object invoke(Object obj, Object... args) 方法赋值获得新的Object对象


注:setAccessible(true)方法可以取消Java语言访问检查(可以访问私有成员方法)











例1:获取类的字节码文件对象的三种方法

// 测试类
public class ReflectTest {
	public static void main(String[] args) throws ClassNotFoundException {

		// 方式1:通过Object类中的getClass() 方法
		Person p1 = new Person();
		Class c1 = p1.getClass();	// 得到Person.class字节码文件对象

		// 创建对象
		Person p2 = new Person();
		Class c2 = p1.getClass();	// Person.class字节码文件对象

		System.out.println(p1 == p2);// false
		System.out.println(c1 == c2);// true

		System.out.println("--------------------");

		// 方式2:通过数据类型的Class属性
		Class c3 = Person.class;	// 加载并且获得person.class字节码文件对象
		System.out.println(c3 == c1);

		System.out.println("----------------------");

		// 方式3:获取类的字节码文件
		// 参数需要类路径:类的全路径名称
		Class c4 = Class.forName("Reflect1.Person");
		System.out.println(c4 == c1);
	}
}


// 自定义Person类
public class Person {
	//成员变量
	private String name ;
	int age ;
	public String address ;
	
	public Person(){}
	
	private Person(String name) {
		this.name = name;
	}
	
	Person(String name,int age){
		this.name = name ;
		this.age = age ;
	}
	
	public Person(String name,int age,String address){
		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
				+ "]";
	}
	
	
}







例2:通过反射获取构造方法(单个私有构造方法)

import java.lang.reflect.Constructor;

public class ConstructorTest {

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

		// 1)获取Person类的字节码文件对象
		Class c = Class.forName("Reflect1.Person");

		// 2)获取私有的构造方法
		// public Constructor getDeclaredConstructor(Class... parameterTypes)
		Constructor con = c.getDeclaredConstructor(String.class);

		// 3)取消 Java 语言访问检查	setAccessible(boolean flag) 强制性可以访问私有构造方法
		con.setAccessible(true);
		// 4)创建构造器的实例对象,可以去传递实际参数
		Object obj = con.newInstance("伊卡尔迪");

		System.out.println(obj);
	}
}

结果:








例3:获取成员变量并使用

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

public class FieldTest {

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

		// 1)通过反射获取字节码文件对象
		Class c = Class.forName("Reflect1.Person");
		
		// 2)创建构造器实例
		Constructor con = c.getConstructor();
		Object obj = con.newInstance();			// Person的实例对象
		
		// 3)获取成员变量并赋值
		// public Field getField(String name):获取公共的指定的字段 参数为当前成员变量名称"address"
		Field addressFiled = c.getField("address");
		// 赋值 public void set(Object obj, Object value)给obj实例对象里面的成员变量设置一个实际参数---->value
		addressFiled.set(obj, "米兰");
		System.out.println(obj);

		System.out.println("-----------------------------");
		// 给name赋值并使用(私有)
		// public Field getDeclaredField(String name):获取类或接口中已经声明的指定的字段
		Field nameField = c.getDeclaredField("name");
		nameField.setAccessible(true);		// 取消Java语言访问检查
		nameField.set(obj, "伊卡尔迪");
		System.out.println(obj);

		System.out.println("-------------------------------");

		// 给age字段赋值并使用
		Field ageField = c.getDeclaredField("age");
		ageField.setAccessible(true);// 取消Java语言访问检查
		ageField.set(obj, 27);

		System.out.println(obj);

	}
}


结果:

【我的Java笔记】Java反射_第1张图片









例4:获取成员方法并使用

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

public class MethodTest {

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

		// 1)通过反射获取字节码文件对象并使用
		Class c = Class.forName("Reflect1.Person");
		// 获取构造器对象,通过构造器创建当前字节码文件的实例对象
		Constructor con = c.getConstructor();
		Object obj = con.newInstance(); // Person对象

		// 2)获取单个成员方法
		/**
		 * public Method getMethod(String name,Class... parameterTypes):指定公共成员方法
		 * 参数1:表示方法名 参数2:该方法的参数类型的Class对象(数据类型的class属性) String.class
		 */
		Method m1 = c.getMethod("show");
		
		/**
		 * public Object invoke(Object obj, Object... args) 参数1:表示当前针对哪个以实例对象进行方法的调用
		 * 参数2:当前调用该方法的时候里面传递的实际参数
		 */
		m1.invoke(obj);

		System.out.println("----------------------------");

		// 3)调用Method方法	public void method(String s)
		Method m2 = c.getMethod("method", String.class);
		m2.invoke(obj, "word");

		System.out.println("----------------------------");

		/**
		 * public String getString(String s, int i) { return s + "---" + i; }
		 */

		// 4)调用getString()方法
		Method m3 = c.getMethod("getString", String.class, int.class);
		Object objString = m3.invoke(obj, "hello",100) ;
		System.out.println(objString);
		
		//String objString = (String) m3.invoke(obj, "hello", 100); // 向上转型
		System.out.println(objString);

		System.out.println("--------------------------");
	
		// 5)调用function()方法	私有方法
		// 该方法是私有的,public Method getDeclaredMethod(String name,Class...
		// parameterTypes)
		Method m4 = c.getDeclaredMethod("function");
		m4.setAccessible(true);// 取消Java语言的访问检查
		m4.invoke(obj);
	}
}


结果:

【我的Java笔记】Java反射_第2张图片


你可能感兴趣的:(【我的Java笔记】Java反射)