day_30Java反射

一、java反射机制

     1.通过了解java的反射机制,程序员可以更深入的控制程序的运行过程实现。

          1.1通过java反射机制,可以在程序中访问已经装载到jvm中的java对象的描述,

实现访问、检测和修改描述java对象本身信息的功能。

 

       java的反射机制就是增加程序的灵活性,避免将程序写死到代码里,

 

例如:

        实例化一个 person()对象, 不使用反射, new person(); 如果想变成 实例化 其他类, 那么必须修改源代码,并重新编译。

扫描二维码关注公众号,回复: 724983 查看本文章

      使用反射: class.forName("person").newInstance(); 而且这个类描述可以写到配置文件中,如 **.xml, 这样如果想实例化其他类,只要修改配置文件的"类描述"就可以了,不需要重新修改代码并编译。

 

http://www.cnblogs.com/13188196we/p/3144288.html

复制过来的:http://zhidao.baidu.com/question/478254128.html

 

注意:

     在通过方法getFields()和getMethods()依次获得权限为public的成员变量和方法时,

将包含从超类中继承的成员变量和方法;

     而通过方法getDeclardFields()和getDeclaredMethods()只是获得在本类中定义的所有成员变量和方法。

 

二、 访问构造方法

  a.在通过下列一组方法访问构造方法时,将返回Constructor类型的对象或数组。

每个Constructor对象代表一个构造方法,利用Constructor对象可以操纵相应的构造方法。

 

        getConstructors()

        getConstructors(Class<?> ...parameterTypes)

        getDeclaredConstructors()

        getDeclaredConstructors(Class<?> ...parameterTypes)

 

b.如果是访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问。

例如:

       ObjectClass.getDeclaredConstructors(String.class,int.class);

       ObjectClass.getDeclaredConstructors(new Class[]{String.class,int.class});

 

Constructor类中提供的常用方法:

 ...

        newInstance(Object...initargs)

 

c.通过该构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参构造方法。

 

       setAccessible(boolean flag) 

 

d.如果该构造方法的权限设置为private,默认为不允许通过反射利用newInstance(Object...initargs)

方法创建对象。如果先执行该方法,并将入口参数设为true,则允许创建。

 

e.通过java.lang.reflect.Modifier类可以解析出getModifire()方法的返回值所表示的修饰信息,

在该类中提供了一系列用来解析的静态方法,既可以查看是否被指定的修饰符修饰,

还可以以字符串的形式获得所有修饰符。

 

       isPublic(int mod) 查看是否被public修饰符修饰,如果是则返回true,否则返回false。

toString(int mod) 以字符串的形式返回所有修饰符。

 

 

f.例如:

           判断对象constructors所代表的构造方法是否被private修饰,以及以字符串形式获得该构造方法的所有修饰符。

 

       int modifiers = constructor.getModifiers();

       boolean isEmbelishByPrivate = Modifier.isPrivate(modifiers);

        String embelshment = Modifier.toString(modifiers);

三、访问成员变量

  3.1、概念

 

      在通过下列一组方法访问成员变量方法时,将返回Field类型的对象或数组。

每个Field对象代表一个成员变量,利用Field对象可以可以操纵相应的成员变量.

 

      getFields()

      getFields(String name)

      getDeclaredFields()

      getDeclaredFields(String name)

 

       如果是访问指定的成员变量,可以通过该成员变量的名称来访问。

例如访问一个名称为birthday的成员变量:

      object.getDeclaredField("birthday");

 

Field提供的常用方法:

       getName() 获得该成员变量的名称

       getType() 获得表示该成员变量类型的Class对象

        get(Object obj,Object value)  将指定对象obj中的该成员变量的值设置为value。

四、访问方法

         在通过下列一组方法访问方法时,将返回Method类型的对象或数组。

每个Method对象代表一个方法,利用Method对象可以操纵相应的方法。

 

         getMethod()

         getMethod(String name,Class<?>... parameterTypes)

 

         getDeclaredMethod()

          getDeclaredMethod(String name,Class<?>... parameterTypes)

 

        如果是访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。

例如

        访问一个名称为print、入口参数类型依次为String和int型的方法

 

          objectClass.getDeclaredMethod("print",String.class,int.class)

 

           objectClass.getDeclaredMethod("print",new Class[]{String.class,int.class})

星期一, 十一月 30, 2015 22:38:28

学习java反射机制,先大致了解原理,看demo,回过头再看原理。

 

 

1、反射指的是程序借助某种手段检查自己结构的一种能力

 

2、http://zhidao.baidu.com/link?url=Sn2ZROQ_koC-MqwObmubL3qApBYV9lJlPOZuW_ngEI1iGXLW-V8MdO6dpxeTaMGcn9lShAnaCj-7Be4PK6vivK

 

   解析:

          Class.forName(xxx.xx.xx) 返回的是一个类 首先你要明白在java里面任何class都要装载在虚拟机上才能运行。

        这句话就是装载类用的(和new 不一样,要分清楚)。

 

       从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。

       但是使用newInstance()方法的时候,就必须保证:

                      1、这个类已经加载;2、这个类已经连接了。

        而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,            即加载 java API的那个加载器。 

 

         现在可以看出,newInstance()实际上是把new这个方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化。

          这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。

 

      最后用最简单的描述来区分new关键字和newInstance()方法的区别: 

             newInstance: 弱类型。低效率。只能调用无参构造。 

             new: 强类型。相对高效。能调用任何public构造。

 

3、代码案例

    

基本类:
package day30;

public class Person {
	String name;
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

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

class SuperMan extends Person implements ActionInterface  {  
    private boolean BlueHair;  
      
	public boolean isBlueHair() {
		return BlueHair;
	}

	public void setBlueHair(boolean blueHair) {
		BlueHair = blueHair;
	}

	public void fly()  
    {  
        System.out.println("超人fly()");  
    }  
      
    public void walk(int m) {  
        // TODO Auto-generated method stub  
        System.out.println("超人walk()" + m);  
    }  
} 

interface ActionInterface{  
    public void walk(int m);  
}  

package day30;

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

public class ReflactTesta {
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
		System.out.println("------通过Java反射机制得到类的包名和类名-----");
		Demo1();
		
		System.out.println();
		System.out.println("----验证所有的类都是Class类的实例对象  ----");
		Demo2();
		
		System.out.println();
		System.out.println("----通过Java反射机制,用Class 创建类对象[这也就是反射存在的意义所在]----");
		Demo3();
		
		System.out.println();
		System.out.println("----通过Java反射机制得到一个类的构造函数,并实现创建带参实例对象 ----");
		Demo4();
	}
	
	public static void Demo1() {
		Person p1 = new Person();
		System.out.println("  获得Demo1包名----"+p1.getClass().getPackage().getName());
		System.out.println("  获得完整的类目----"+p1.getClass().getName());
	}
	
	
	 public static void Demo2() throws ClassNotFoundException  
	    {  
	        //定义两个类型都未知的Class , 设置初值为null, 看看如何给它们赋值成Person类  
	        Class<?> class1 = null;  
	        Class<?> class2 = null;  
	          
	        //写法1, 可能抛出 ClassNotFoundException [多用这个写法]  
	        class1 = Class.forName("day30.Person");  //设置为Person类
	        System.out.println("Demo2:(写法1) 包名: " + class1.getPackage().getName() + ","   
	                + "完整类名: " + class1.getName());  
	          
	        //写法2  
	        class2 = Person.class; //赋值成Person类   
	        System.out.println("Demo2:(写法2) 包名: " + class2.getPackage().getName() + ","   
	                + "完整类名: " + class2.getName());  
	    }  
	
	 //Demo3: 通过Java反射机制,用Class 创建类对象[这也就是反射存在的意义所在] 
	 /* newInstance()实际上是把new这个方式分解为两步,
	     即首先调用Class加载方法加载某个类,然后实例化。*/
	 public static void Demo3() throws ClassNotFoundException, InstantiationException, IllegalAccessException  
	    {  
	        Class<?> class1 = null;  
	        class1 = Class.forName("day30.Person");  
	        //由于这里不能带参数,所以你要实例化的这个类Person,使用无参构造方法
	        Person person = (Person) class1.newInstance();  
	        person.setAge(24);  
	        person.setName("waxun..");  
	        System.out.println("Demo3: " + person.getName() + "    " + person.getAge());  
	    }  
	
	 //通过Java反射机制得到一个类的构造函数,并实现创建带参实例对象 
	 public static void Demo4() throws ClassNotFoundException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException  
	    {  
	        Class<?> class1 = null;  
	        Person person1 = null;  
	        Person person2 = null; 
	        Person person3 = null; 
	          
	        class1 = Class.forName("day30.Person");  
	        Constructor<?>[] constructors = class1.getConstructors();  //获取类中所有的构造方法,得到一系列构造函数集合  
	        person1 = (Person) constructors[0].newInstance(); 
	        person1.setName("yuzhou"); 
	        person1.setAge(24);  
	          
	        person2 = (Person) constructors[1].newInstance("xiner",25);  
	        person3 = (Person) constructors[1].newInstance("xiner_b",25);
	          
	        System.out.println("Demo4: " + person1.getName() + " : " + person1.getAge()  
	                + "  ,   " + person2.getName() + " : " + person2.getAge()  
	                ); 
	        System.out.println("Demo4: "+person3.getName() + " : " + person3.getAge()  
	                ); 
	          
	    }  
	 
	 
}
运行结果:
------通过Java反射机制得到类的包名和类名-----
  获得Demo1包名----day30
  获得完整的类目----day30.Person

----验证所有的类都是Class类的实例对象  ----
Demo2:(写法1) 包名: day30,完整类名: day30.Person
Demo2:(写法2) 包名: day30,完整类名: day30.Person

----通过Java反射机制,用Class 创建类对象[这也就是反射存在的意义所在]----
Demo3: waxun..    24

----通过Java反射机制得到一个类的构造函数,并实现创建带参实例对象 ----
Demo4: yuzhou : 24  ,   xiner : 25
Demo4: xiner_b : 25

 

 

4、代码案例2

package day30;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;



public class ReflactTestb {
	public static void main(String[] args) throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException, InstantiationException, ClassNotFoundException {
		System.out.println("---- 通过Java反射机制操作成员变量, set 和 get----");
		Demo5();
		
		System.out.println("----通过Java反射机制得到类的一些属性: 继承的接口,父类,函数信息,成员信息,类型等----");
		Demo6();
	}
	
	 public static void Demo5() throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException, InstantiationException, ClassNotFoundException  
	    {  
	        Class<?> class1 = null;  
	        class1 = Class.forName("day30.Person");  
	        Object obj = class1.newInstance();  
	        /*java.lang.Class<T>
	         *getDeclaredField(String name) 
	         *返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。*/
	        Field personNameField = class1.getDeclaredField("name");  
	        /*java.lang.reflect.AccessibleObject
	         *setAccessible(boolean flag)将此对象的 accessible 标志设置为指示的布尔值。
	         */
	        personNameField.setAccessible(true);  
	        /*set(Object obj, Object value)
	         * 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。*/
	        personNameField.set(obj, "宇宙歆儿");  
	         
	        //get(Object obj)返回指定对象上此 Field 表示的字段的值。
	        System.out.println("Demo5: 修改属性之后得到属性变量的值:" + personNameField.get(obj));  
	          
	    }  
	 
	 public static void Demo6() throws ClassNotFoundException{
		 Class<?> class1 = null;
		 class1 = class1.forName("day30.SuperMan");
		 //取得父类的名字
		 Class<?> class2 = class1.getSuperclass();
		 System.out.println("取得superman的父类名: "+class2.getName());
		 
		 Field[] fields = class1.getDeclaredFields();//获得所表示的类或接口的指定已声明字段
		 for(int i = 0 ; i < fields.length ; i++ ) {
			 System.out.println("类中的成员为: "+fields[i]);
		 }
		//取得类方法
		 Method[] methods = class1.getDeclaredMethods();
		 for(int i = 0;i<methods.length;i++) {
			System.out.println("函数名 : "+methods[i].getName()); 
			System.out.println("函数返回值类型:   "+methods[i].getReturnType());
			System.out.println("函数访问修饰符:" + Modifier.toString(methods[i].getModifiers()));  
	        System.out.println("函数代码写法: " + methods[i]);  
		 }
		 
		//取得类实现的接口,因为接口类也属于Class,所以得到接口中的方法也是一样的方法得到哈  
	        Class<?> interfaces[] = class1.getInterfaces();  
	        for (int i = 0; i < interfaces.length; i++) {  
	            System.out.println("实现的接口类名: " + interfaces[i].getName() );  
	        }  
		 
	 }
	      
	 
}

运行结果:
---- 通过Java反射机制操作成员变量, set 和 get----
Demo5: 修改属性之后得到属性变量的值:宇宙歆儿
----通过Java反射机制得到类的一些属性: 继承的接口,父类,函数信息,成员信息,类型等----
取得superman的父类名: day30.Person
类中的成员为: private boolean day30.SuperMan.BlueHair
函数名 : isBlueHair
函数返回值类型:   boolean
函数访问修饰符:public
函数代码写法: public boolean day30.SuperMan.isBlueHair()
函数名 : setBlueHair
函数返回值类型:   void
函数访问修饰符:public
函数代码写法: public void day30.SuperMan.setBlueHair(boolean)
函数名 : fly
函数返回值类型:   void
函数访问修饰符:public
函数代码写法: public void day30.SuperMan.fly()
函数名 : walk
函数返回值类型:   void
函数访问修饰符:public
函数代码写法: public void day30.SuperMan.walk(int)
实现的接口类名: day30.ActionInterface

 

 

 

5、代码案例3

 

package day30;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflactTestc {
	public static void main(String[] args) throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
		System.out.println("---- 通过Java反射机制调用类中方法----");
		Demo7();
		System.out.println();
		System.out.println("----通过Java反射机制获得类加载器----");
		Demo8();
	}
	
	 public static void Demo7() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException {
		/*java.lang.reflect.Method
		 * Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。
		 * 所反映的方法可能是类方法或实例方法(包括抽象方法)。 */
		 
		 /*java.lang.Class<T>
		  * getMethods() 返回一个包含某些 Method 对象的数组,
		  *这些对象反映此 Class 对象所表示的类或接口
		  *(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。*/
		 Class<?> class1 = null;  
	        class1 = Class.forName("day30.SuperMan");  
	          
	        System.out.println("Demo7: \n调用无参方法fly():");  
	        Method method = class1.getMethod("fly");  
	        method.invoke(class1.newInstance());  
	          
	        System.out.println("调用有参方法walk(int m):");  
	        method = class1.getMethod("walk",int.class);  
	        method.invoke(class1.newInstance(),100); 
	 }
	 
	   /** 
	     * Demo8: 通过Java反射机制得到类加载器信息 
	     *  
	     * 在java中有三种类类加载器。[这段资料网上截取] 
	 
	        1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。 
	 
	        2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类 
	 
	        3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。 
	     *  
	     * @throws ClassNotFoundException  
	     */  
	    public static void Demo8() throws ClassNotFoundException  
	    {  
	        Class<?> class1 = null;  
	        class1 = Class.forName("day30.SuperMan");  
	        String nameString = class1.getClassLoader().getClass().getName();  
	          
	        System.out.println("Demo8: 类加载器类名: " + nameString);  
	    }  	   
}

运行结果:
---- 通过Java反射机制调用类中方法----
Demo7: 
调用无参方法fly():
超人fly()
调用有参方法walk(int m):
超人walk()100

----通过Java反射机制获得类加载器----
Demo8: 类加载器类名: sun.misc.Launcher$AppClassLoader




JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能:在运行时判定任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判定任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

 

猜你喜欢

转载自yuzhouxiner.iteye.com/blog/2260647