黑马程序员-----java反射总结*


---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------


一、java的反射机制概述

反射和类的关系:在程序运行状态中,对于任意一个类(指.class文件),都能够知道这个类所有的属性和方法

反射和类对象的关系:反射对于某个类的对象,都能够调用它的任意一个方法和属性

 

概念:动态获取类的信息以及动态调用类对象的方法和属性的功能称为java语言的反射机制

好处:提高了程序的扩展性

该好处与多态的好处比较:通过反射可以省略new子类对象这个步骤,直接将类名以字符串的形式传递到forName的参数列表中来创建此类实例

Java反射有什么作用呢?

假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,但第二个程序员并没完成他所写的类。那么第一个程序员的代码能否通过编译呢?这是不能通过编译的。利用Java反射的机制,就可以让第一个程序员在没有得到第二个程序员所写的类的时候,来完成自身代码的编译。


 

 

二、Class类对象的获取方法

1、java对字节码(.class)文件进行了抽象,用class类来描述

2、Class对象的源码:public final class Class<T>{.......}

     final:表示该类不能够被继承

     Class类是一个泛型类,T表示Class类对象所属哪个类

     Class类没有构造方法,不能够new对象,这种方式是绝对错误的:Class c = new Class();

 

3、获取Class类对象的五种途径

  • 非静态方法getClass():对象名.getClass()

缺点:此种方式创建类对象还需要明确类并创建对象

  • 静态属性:class:属性名.class(属性可以是数组、字符串、基本数据类型、类等)
缺点:此种方式创建类对象也需要明确类,扩展性差
  • 静态方法Class.forName():参数列表中传入某类的全类名(例如java.lang.Integer)

优点:仅仅需要类名以字符串的形式传入即可获得class类对象,这种方式最为常见,最为简单

  • 非静态方法getSuperclass:对象名.getSuperclass()
此种方式是返回该类Class对象的父类的Class对象

  • TYPE
包装类的专属创建Class对象方式


面试题:以上方法的作用是?

作用:返回某个类的字节码文件对象,也就是Class对象

注意:

1、如果字节码文件已被加载,那么forName直接返回

2、如果字节码文件还未加载,那么JVM就指示类加载器去加载该文件,并把加载完的字节码文件放入缓冲区,再返回



3、Class对象的常用方法

八种基本数据类型对应八个Class实例对象

基本数据类型对应的Class实例对象不等于包装类对应的Class实例对象

只要是数据类型,就有对应的实例对象

1、获取空参数构造方法并创建对象实体

获取空参构造方法:public T newInstance() throws InstantiationException,IllegalAccessException;

InstantiationException异常:如果该类中没有空参构造 方法,则报该异常

IllegalAccessException异常:如果该类中默认空参构造方法的权限修饰符是private而不是public,则报该异常

public static void getConstructor1(){  
    try{  
       Stringname ="cn.itcast.Person";  
       Class clazz =Class.forName(name); 
       //调用newInstance方法时,会自动调用Person类的空参构造方法创建Person对象 
       Objectob j = clazz.newInstance();  
    }catch(ClassNotFoundException cnfe){  
       sop(cnfe.toString());  
    }catch(InstantiationException ite){  
       sop(ite.toString());  
    }catch(IllegalAccessException iae){  
       sop(iae.toString());  
    }  
}  


2、获取非空参数构造方法并创建爱你对象实体

获取非空参数构造方法:getConstructor方法 public Constructor<T> getConstructor(Class<?> ...parameterTypes) throws NosuchMethodWxception,SecurityException

package cn.itcast.ly;

import java.lang.reflect.*;

public class Demo {
	public static void main(String[] args) throws Exception{
		//第一步:创建Class对象实例
		Class cla = Class.forName("cn.itcast.ly.Person");
		//第二步:创建一个数组
		Class[] clas = new Class[]{String.class,int.class};
		//第三步:获取构造方法Class类实体
		Constructor con = cla.getConstructor(clas);
		//第四步:根据Constructor类的newInstance方法创建实体,
		//源码:public T newInstance(Object... initargs)
		Object[] objs = new Object[]{"Tom",20}; 
		Object obj = con.newInstance(objs);
		//第五步:打印
		System.out.println(obj);
	}
}

class Person{
	public Person(String name,int age){
		
	}
}




4、Constructor类中的方法

1、getConstructors()方法

该方法是获取该类中所有构造方法,返回Constructor数组

2、getConstructor()方法和newInstance()方法

该方法时获取到指定参数的构造方法

public class Demo {
	public static void main(String[] args)throws Exception {
		/*Constructor[] c = Class.forName("java.lang.String").getConstructors();
		for(Constructor con : c){
			System.out.println(con);
		}*/
		method();
	}
	
	public static void method() throws Exception{
		/*
		 * 源码:
		 * Constructor<T> getConstructor(Class<?>... parameterTypes)
		 * 
		 * public T newInstance(Object... initargs)
         	 *	throws InstantiationException,
         	 *              IllegalAccessException,
         	 *              IllegalArgumentException,
         	 *              InvocationTargetException
		 * */ 
		
		//第一步:通过Class类对象调用getConstructor方法获取指定参数类型的构造函数
		Constructor c = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
		//第二步:通过Constructor对象调用newInstance方法传入参数获取构造方法并实例化对象
		String str = (String)c.newInstance(new StringBuffer("abc"));
		System.out.println(str.charAt(2)); 
	}
}

3、getConstructor(Class<?>... parameterTypes)方法

该方法时获取到多个参数的构造函数

public class ClassDemo{
	
	public static void main(String[] args)throws Exception {
		//第一步:获取到相应Class类对象
		Class cla = Class.forName("cn.itcast.Class.Person");
		//第二步:设置参数数组
		Class[] clas = new Class[]{double.class,int.class};
		//第三步:获取Constructor对象
		Constructor con = cla.getConstructor(clas);
		//第四步:设置参数数组
		Object[] objs = new Object[]{3.1415,2};
		//第五步:生成实例对象
		Object obj = con.newInstance(objs);
		//第六步:打印
		System.out.println(obj);
	}
}

class Person{
	private double d;
	private int i;
	public Person(double d,int i){
		this.d = d;
		this.i = i;
	}
}




5、Field类

1、Field类源代码:public final class reflect extends AccessibleObject implements Member{.....}

2、Field类属于java.lang.reflect包

3、Field类不能够被继承,不是泛型类,是AccessibleObject类的子类


六种方法:

一、getFields()方法:public Field[] getFields()throws SecurityException {…}

功能:获取类中public修饰的成员字段

二、getDeclaredFields()方法:public Field[] getDeclaredFields()throws SecurityException {…}

功能:获取类中所有修饰符的成员字段

三、getField(String name)方法:public Field getField(String name)throws NoSuchFieldException,SecurityException {…}

功能:根据给定的字段名获取类中public修饰的该字段对象

四、getDeclaredField(String name)方法:public Field getDeclaredField(String name) throws NoSuchFieldException,SecurityException {…}

功能:根绝给定的字段名获取类中所有修饰的该字段对象

五、set(Object obj, Object value)方法:public void set(Object obj, Object value) throws IllegalArgumentException,IllegalAccessException{…};

功能:设置该字段对象与Field关联的值

六、get(Object obj)方法:public Object get(Object obj) throws IllegalArgumentException,IllegalAccessException{…};

功能:获取该字段对象与Filed相关联的值

		/*以下是获取属性*/
		Class cla_2 = Class.forName("cn.itcast.ly.Person");
		/*只能访问public修饰的
		Field fie = cla_2.getField("name");
		fie.set(obj,"liuyang");
		Object str = fie.get(obj);
		System.out.println((String)str);*/
		Field fie = cla_2.getDeclaredField("name");
		fie.setAccessible(true);
		fie.set(obj, "liuyang");
		Object str = fie.get(obj);
		System.out.println((String)str);
		
	}
}

class Person{
	private String name;
	public Person(String name,int age){
		
	}
	public static String method(String name,int age){
		return name;
	}
}



操作非公有字段的步骤:

1、首先调用getDeclaredField(String name)方法获取指定的字段对象

Filed filed = Class.forName("java.lang.String").getDeclaredField("abc");

2、在取消对反射的对象进行权限检查的机制:

field.setAccessible(true);




6、Method方法

1、Method方法源代码:public final class Method extends AccessibleObject implements …{…}

2、Field类属于java.lang.reflect包

3、Field类不能够被继承,不是泛型类,是AccessibleObject类的子类


五种方法:

一、getMethods()方法:public Field[] getFields()throws SecurityException {…}

功能:获取类中public修饰的成员字段

二、getDeclaredMethods()方法:public Field[] getDeclaredFields()throws SecurityException {…}

功能:获取类中所有修饰符的成员字段

三、getMethod(String name,Class<?>…parameterTypes)方法:public Field getField(String name)throws NoSuchFieldException,SecurityException {…}

功能:根据给定的字段名和参数列表获取类中public修饰的该字段对象(如无参数则为null)

四、getDeclaredMethod(String name,Class<?>…parameterTypes)方法:public Field getDeclaredField(String name) throws NoSuchFieldException,SecurityException {…}

功能:根据给定的字段名和参数列表获取类中所有修饰的该字段对象(如无参数则为null)

五、invoke(Object obj, Object... args)方法:public Object invoke(Object obj, Object... args)throws …;

功能:获取指定的方法。参数列表中的第一个obj代表的是调用该方法的对象,

		/*以下是获取方法的结果*/
		Class cla_1 = Class.forName("cn.itcast.ly.Person");
		Class[] clas_1 = new Class[]{String.class,int.class};
		Method met = cla_1.getMethod("method", clas_1);
		Object[] obj_1 = new Object[]{"haha",12};
		//返回方法的结果
		Object obj_2 = met.invoke(obj,obj_1);
		System.out.println(obj_2);
	}
}

class Person{
	public Person(String name,int age){
		
	}
	public static String method(String name,int age){
		return name;
	}
}




操作非公有字段的步骤:

1、首先调用getDeclaredMethod(String name)方法获取指定的字段对象

Method method = Class.forName("java.lang.String").getDeclaredMethod("abc");

2、在取消对反射的对象进行权限检查的机制:

field.setAccessible(true);


调用静态方法:invoke方法第一个参数设为null即可





 

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值