黑马程序员——反射

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


反射

反射,在运行时,动态分析或使用一个类进行工作。
反射是一套 API,是一种对底层的对象操作技术
类加载
类加载,生成.class文件,保存类的信息
类对象,是一个描述这个类信息的对象,对虚拟机加载类的时候,就会创建这个类的类对
象并加载该对象。
Class,是类对象的类。称为类类。只有对象才会被加载到虚拟机中。一个类只会被加载
一次。
2、获得类对象的三种方式:(类对象不用 new 的方法得到的)
1)也可以用 类名.Class,获得这个类的类对象。
2)用一类的对象掉用 a.getClass(),得到这个对象的类型的类对象。
3)也可以使用 Class.forName(类名)(Class 类中的静态方法),也可以得到这个类的类对象,
(注意,这里写的类名必须是全限定名(全名),是包名加类名,XXX.XXX.XXXX)。

强制类加载,这种方法是经常使用的。
一个类的类对象是唯一的。
在使用 Class.forName(类名)时,如果使用时写的类名的类,还没有被加载,则会加载这个类。
Class c;
c.getName(); 返回类名
c.getSuperclass(); 这个方法是获得这个类的父类的类对象。
c.getInterfaces(); 会获得这个类所实现的接口,这个方法返回是一个类对象的数组。


方法对象是类中的方法的信息的描述。

java.lang.reflect
类 Method
--java.lang.Object
  --java.lang.reflect.AccessibleObject
      --java.lang.reflect.Method
所有已实现的接口:
AnnotatedElement, GenericDeclaration, Member


java.lang.reflect.Method,方法类的对象可以通过类对象的 getMethods() 方法获得,获得的是一个方法对象的数组,获得类中的定义的所有方法对象,除了构造方法。


构造方法对象,是用来描述构造方法的信息。

java.lang.reflect
类 Constructor<T>
java.lang.Object
  --java.lang.reflect.AccessibleObject
      --java.lang.reflect.Constructor<T>

类型参数:
T - 在其中声明构造方法的类。
所有已实现的接口:
AnnotatedElement, GenericDeclaration, Member

java.lang.reflect.Constructor 构造方法类的对象可以通过类对象的 getConstructors()方法获得,获得这个类的所有构造方法对象。

属性对象,使用来描述属性的信息。

java.lang.reflect
类 Field

java.lang.Object
--java.lang.reflect.AccessibleObject
   --java.lang.reflect.Field

Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
所有已实现的接口:AnnotatedElement, Member

getFields() 返回一个包含某些Field 对象的数组,这些对象反映此Class 对象所表示的类或接口的所有可访问公共字段。

public class TestClass {
	public String publicVoid() {
		return "运行了 publicVoid方法";
	}

	void defaultVoid() {
		System.out.println("运行了DefaultVoid方法!!!!!");
	}

	private String privateInt(int i) {
		return "运行了 privateInt方法,参数值:" + i;
	}

	static String staticVoidString(String s) {
		return "运行了staticVoidString方法,参数值:" + s;
	}

	public void test(int a) {
		System.out.println(a + "int parameter method");
	}

	public void test(Integer a) {
		System.out.println(a + "Integer parameter method");
	}

	public String toString() {

		return "name";
	}
}

在反射时,如果我直接调用私有方法,会出现
Exception in thread "main" java.lang.IllegalAccessException: Class ClassTest can not access a member of class TestClass with modifiers "private"
    at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
    at java.lang.reflect.Method.invoke(Method.java:588)
    at ClassTest.main(ClassTest.java:29)

        TestClass class1 = new TestClass();
        // 类加载
        Class c1 = TestClass.class;
        Class c2= Class .forName("TestClass");
        Class c3 = class1.getClass();
        System.out.println(c1);
        System.out.println(c3);

        // --1 调用一个类的公开方法并且有返回值但是无参数
        Method m1 = c3.getMethod("publicVoid");
        // null是因为publicVoid()是个无参的方法,当然也可以填写一个长度为0的数组
        Object res1 = m1.invoke(class1, null);
        System.out.println("方法1的测试结果返回值为:\t" + res1);

        // --2 调用一个权限为default方法并且返回值为Void但是无参数

   // getMethod方法只能访问公开的方法。但是getDeclaredMethod只能访问子类声明的方法,不过可以访问私有方法。
        Method m2 = c3.getDeclaredMethod("defaultVoid");
        // 访问有权限的方法时,需使用此方法设置访问性,否则会因为权限不够无法访问。
        m2.setAccessible(true);
        // 填写一个长度为0的数组是因为defaultVoid()是个无参的方法,当然也可以填null
        Object res2 = m2.invoke(class1, new Object[0]);

        System.out.println("方法2的测试结果返回值为:\t" + res2);
        // --3 调用一个私有的方法并且有返回值有基本类型int参数
        Method m3 = c3.getDeclaredMethod("privateInt", int.class);

        m3.setAccessible(true);
        // null是因为publicVoid()是个无参的方法,当然也可以填写一个长度为0的数组
        Object res3 = m3.invoke(class1, new Integer(3));
        System.out.println("方法3的测试结果返回值为:\t" + res3);
        // --4 调用一个静态的方法并且有返回值有String类型的参数
        Method m4 = c3.getDeclaredMethod("staticVoidString", String.class);
        m4.setAccessible(true);
        Object res4 = m4.invoke(class1, "测试4");
        System.out.println("方法4的测试结果返回值为:\t" + res4);
        Method m5 = c3.getDeclaredMethod("test", int.class);

        Method m6 = c3.getDeclaredMethod("test", Integer.class);
        System.out.println(int.class);
        System.out.println(Integer.class);
        Integer in = Integer.valueOf(3);
        m5.invoke(class1, 1);
        m6.invoke(class1, in);
        m5.invoke(class1, 1);
        m6.invoke(class1, in);

        class1.test(1);
        class1.test(in);
 

int 和Integer对象是可以自动转换的,但是在反射情况下,作为参数时二者是不同的类型的。
在test(int i)和test(Integer in)同时存在的情况下,如果调用的是方法中是Integer对象,则不进行自动拆包转换,而是直接调用test(Integer in)方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值