27. 复习反射的内容

 

1.取得Class类对象的三种方式

public class Test{
	public static void main(String[] args) {
		try{
			Class clazz1 = String.class;
			Class clazz2 = "String".getClass();
			Class clazz3 = Class.forName("java.lang.String");//这里写成了"java.lang.string" String类的S是大写的,要注意
		}catch(ClassNotFoundException e){
			e.printStackTrace();
		}
	}
}


写错的地方:

(1) forName方法throws ClassNotFoundException

(2) "java.lang.String"写成"java.lang.string" ,String类的S是大写的

2.预定义的九种Class对象(8种数据类型+void)

public class Test {
	public static void main(String[] args) {
		sop(int.class == Integer.class); // false
		sop(float.class == Float.class); // false
		sop(int[].class.isPrimitive()); // false
		int a = 3;
		sop(int.class == Integer.TYPE); // true
		// Integer.TYPE → public static final Class<Integer> TYPE = (Class<Integer>)Class.getPrimitiveClass("int");
	}

	public static void sop(Object obj) {
		System.out.println(obj);
	}
}

注意的地方:

(1) 【背单词】isPrimitive() 判定指定的 Class 对象是否表示一个基本类型

(2)  是 “Integer.TYPE” 而不是 "Integer.Type" ,TYPE四个字母都是大写的

(3)  注意 “int.class == Integer.class”为false ( int和Integer虽然是基本类型与包装类的关系,

      但它俩的.class是Class类的两个不同实例对象 )

(4) “Integer.TYPE” 其实就是Class的getPrimitiveClass方法得到的全局常量

(5)  int.getClass()会出错 ,因为getClass()是Object类的方法,因此基本数据类型不能用getClass()方法

3.Mehod类的基本印象

import java.lang.reflect.*; //注意这里

public class Test{
	public static void main(String[] args){
		try{
			Method string_CharAt = "abc".getClass().getMethod("charAt",int.class); //注意这里
			char a = (char)string_CharAt.invoke("abc",2); //注意这里
			System.out.println(a);
		}catch(NoSuchMethodException e){
			e.printStackTrace();
		}catch(InvocationTargetException e){  //注意这里
			e.printStackTrace();
		}catch(IllegalAccessException e){ //注意这里
			e.printStackTrace();
		}
	
	}

}

注意的地方:

(1)  要引入反射的包,并且不是 "import java.reflect.*" ,而是"import java.lang.reflect.*"

(2)  getMethod(String name, Class<?>... parameterTypes) ,getMehod方法的第一个参数是String对象,第二个是Class对象

(3)  抛出的异常:getMehod抛NoSuchMethodException ,invoke抛IllegalAccessException和InvocationTargetException

     注意IllegalAccessException是"爱ll"不是"爱爱爱"开头,是"InvocationTargetException"而不是"InvocationException"

(4)  invoke方法的返回值是Object类型,要强制转换

4.Field类的基本印象 与 暴力反射

import java.lang.reflect.*; 

public class Test{
	public static void main(String[] args){
		try{
			Person p = new Person("Tom",12);
			Field field_Name = p.getClass().getField("name");
			Field field_Age = p.getClass().getDeclaredField("age");
			field_Name.set(p,"Jimmy");
			field_Age.setAccessible(true);
			field_Age.set(p,13);
			System.out.println(p.name+" - "+p.getAge());
		}catch(NoSuchFieldException e){
			e.printStackTrace();
		}catch(IllegalAccessException e){
			e.printStackTrace();
		}
	}

}

class Person{
	public String name;
	private int age;
	
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	
	public int getAge(){
		return this.age;
	}
}

注意的地方:

(1)  getField的参数是String类型,抛NoSuchFieldException 

(2)  Field对象的set方法参数是(Object obj, Object value) 

(3)  【背单词】 getDeclaredField 、setAccessible

5.Constructor类的基本印象

import java.lang.reflect.*;

public class Test {
	public static void main(String[] args) {
		try {
			Constructor constructor_Person = Person.class.getConstructor(String.class, int.class);
			Person p = (Person) constructor_Person.newInstance("Tom", 12);
			System.out.println(p.name + " - " + p.getAge());
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		}
	}
}

class Person {
	public String name;
	private int age;

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

注意的地方:

(1)  【背单词】Constructor ,是"newInstance"而不是"newInstace"

(2)  newInstance(Object... initargs)的返回值也是Object,要转换

(3)  newInstance会抛出InstantiationException

6.小练习

import java.lang.reflect.*;
import java.util.*;

//题目:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的“b”改为“a”
public class Test {

	public static void main(String[] args) throws IllegalArgumentException,
			IllegalAccessException {
		Person p = new Person("abcabc", "b", 12);
		Field[] fieldsOfPerson = Person.class.getDeclaredFields(); //注意这里
		for (Field f : fieldsOfPerson) {
			f.setAccessible(true);
			if (f.getType() == String.class) {  //注意这里
				String oldValue = (String) f.get(p);
				String newValue = oldValue.replace('b', 'a');
				f.set(p, newValue);
			}
		}
		System.out.println(p);
	}
}

class Person {

	public String name;
	private String className;
	private int age;

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

	public String getName() {
		return this.name;
	}

	@Override
	public String toString() {
		return this.name + " - " + this.className + " - " + this.age;
	}
}

注意的地方:

判断成员变量类型不是 if(f instanceof String)也不是 if(f.getClass()==String.class),

而是if (f.getType() == String.class)!

7.数组的反射

import java.lang.reflect.*;

public class Test {

	public static void main(String[] args) {
		int[] i = { 1, 2, 3 };
		System.out.println(Array.getLength(i));
	}
}


java.lang.reflect.Array用于完成对数组的反射操作。

8.关于反射抛的异常

刚开始没有借助Eclipse这样的软件,完全自己写try……catch,

真的没想到反射的程序居然需要捕抓这么多异常。

成员变量、成员方法、构造方法的程序,每次后面都跟着两到四个异常,

不过多写几次,就发现其中其实有规律可循。

例如反射取成员,有可能根本没有这个成员,因此就有NoSuchMethodException和NoSuchFieldException,

有例如反射使用成员方法和构造方法,有可能调用出错,或者访问权限不足,就有了 IllegalAccessException和 InvocationTargetException等等。

每次使用这些方法的时候思考一下,再多写几次,就能避免没有捕抓某个异常的情况了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值