现在的位置: 首页 > 综合 > 正文

黑马程序员_【java高新技术】反射机制

2014年09月05日 ⁄ 综合 ⁄ 共 7798字 ⁄ 字号 评论关闭

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

Java反射机制

概念反射就是把java类中的各种成分映射成相应的java类,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。例如,一个java类用一个Class类的对象来表示,一个类中的组成部分:成员变量,成员方法,构造方法,包等等信息也用一个个的java类来表示。就好比汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类,表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应的实例对象来表示,它们是FieldMethod,Constructor,Package等等。

 

一个类中的每个成员都可以用相应的反射API的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象,学习和应用反射的要点就是研究这些实例对象的作用和用法。

1.构造方法的反射应用Constructor

Constructor类代表某个类中的一个构造方法

得到某个类所有的构造方法:

Constructor[]  constructors = Class.forName("java.lang.String").getConstructor();

得到某个类某一个构造方法:

Constructor constructor =Class.forName("java.lang.String").getConstructor(StringBuffer.class);

创建实例对象:

通常方式:String str = new String(new StringBuffer("abc"));

反射方式:String str = (String)constructor.newInstance(newStringBuffer("abc"));

 

Class.newInstance()方法应用:

例子:String obj =(String)Class.forName("java.lang.String").newInstance();

该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

注:该方法内部代码用到了缓存机制来保存默认构造方法的实例对象。

 2.成员变量的反射应用Field

Field类代表某个类中的一个成员变量

得到的Field对象是对应到类上面的成员变量。原因:类只有一个,而该类的实例对象有多个,如果是与对象关联,那关联的是哪个对象呢?所以字段fieldX代表的是x的定义,而不是具体的x变量。(示例代码见:reflecttest.java

 3.成员方法的反射应用Method

Method类代表某个类中的一个成员方法

得到类中的某一个方法:

Method  charAt =  Class.forName("java.lang.String").getMethod("charAt",int.class);

 调用方法:

通常方式:str.charAt(1);

反射方式charAt.invoke(str,1);

如果传递给Method对象的invoke()方法的第一个参数为null,这没有什么意义,说明Method对象对应的是一个静态方法

 4.用反射方式执行某个类中的main方法:

目标:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法

问题:

启动java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法的,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac到底会按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new
String[]{"xxx"}),javac
只把它当作jdk1.4的语法进行理解,而不把空当作jdk1.5的语法解释,因此会出现参数类型不对的问题。

 解决办法:

mainMethod.invoke(null,new Object[]{newString[]{"xxx"}});

mainMethod.invoke(null,(Object)new String[]{"xxx"});编译器会作特殊处理,编译时不把参数当作数组看待,也就不会将数组打散成若干个参数了。

5.数组的反射:

1.具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。

2.代表数组的Class实例对象的getSuperclass()方法返回的父类为Object对应的Class.

3.基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。

4.Arrays.asList()方法处理int[]String[]时的差异。

Arrays工具类用于完成对数组的反射操作。

反射的作用-->实现框架功能:

框架:

通俗易懂的框架解读:我建房子卖给用户住,由用户自己安装门窗和空调,我建的房子就是框架,用户需要用我的框架,把门窗插入进我提供的框架中。框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类

框架要解决的核心问题:

我在写框架(房子)时,你这个用户可能还在上小学,还不会写程序,我写的框架程序怎样能调用到你以后写的类(门窗)呢?

因为在写程序时无法知道要被调用的类名,所以,在程序中无法直接new某个类的实例对象,而要用反射方式来做。

综合案例:(代码见:ReflectTest.java,ReflectTest2.java

 示例代码:

ReflectTest.java

package cn.itcast.day1;

import java.lang.reflect.Array;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.util.Arrays;

 

public class ReflectTest {

 
         @SuppressWarnings("unchecked")

         publicstatic void main(String[] args) throws Exception {

                   Stringstr = "abc";

                   Class<String>cls1 = (Class<String>) str.getClass();  //三种得到字节码的方式

                   Class<String>cls2 = String.class;

                   Class<String>cls3 = (Class<String>) Class.forName("java.lang.String");

                   System.out.println(cls1== cls2);//true

                   System.out.println(cls1== cls3);//true

                   

                   System.out.println(cls1.isPrimitive());

                   System.out.println(int.class.isPrimitive());

                   System.out.println(int.class== Integer.class);

                   System.out.println(int.class== Integer.TYPE);

                   

                   Constructorconstructor = String.class.getConstructor(StringBuffer.class);

                   Stringstr1 = (String)constructor.newInstance(new StringBuffer("abc"));

                   //Stringstr1 = (String)constructor.newInstance("abc");//argument typemismatch

                   System.out.println(str1.charAt(2));

                   

                   ReflectPointpt1 = new ReflectPoint(3, 5);

                   FieldfieldY = pt1.getClass().getField("y");

                   //fieldY的值是多少?是5,错!!fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值。

                   System.out.println(fieldY.get(pt1));

                   

                   FieldfieldX = pt1.getClass().getDeclaredField("x");

                   fieldX.setAccessible(true);//暴力反射

                   System.out.println(fieldX.get(pt1));

                   

                   //System.out.println(pt1);

                   changeStringValue(pt1);

                   System.out.println(pt1);

                   

                   //成员方法反射。

                   MethodmethodCharAt = String.class.getMethod("charAt", int.class);

                   System.out.println(methodCharAt.invoke(str,1));

                   System.out.println(methodCharAt.invoke(str,new Object[]{2}));

                   

                   //用反射方式执行某个类中的main方法。

                   StringstartingClassName = args[0];

                   MethodmainMethod = Class.forName(startingClassName).getMethod("main",String[].class);

                   mainMethod.invoke(startingClassName,new Object[]{newString[]{"adf","fghh","asdth"}});//记得给程序进行运行配置

                   //mainMethod.invoke(startingClassName,(Object)new String[]{"adf","fghh","asdth"});

                   

                   

                   //数组与Object的关系及其反射类型

                   int[]a1 = new int[]{1,2,3};

                   int[]a2 = new int[4];

                   int[][]a3 = new int[2][3];

                   String[]s1 = new String[]{"a","b","c"};

                   System.out.println(a1.getClass()==a2.getClass());

                   //System.out.println(a1.getClass()== a3.getClass());
                   //System.out.println(a1.getClass()== s1.getClass());

                   System.out.println(a1.getClass().getName());

                   System.out.println(a1.getClass().getSuperclass().getName());

                   System.out.println(s1.getClass().getSuperclass().getName());

                   

                   Objectobj1 = a1;//a1数组的父类就是object,所以赋值成功

                   Objectobj2 = s1;//String的父类是Object

                   //Object[]obj3 = a1;//不行的,object数组里面装的应该是object,而将a1数组赋给object数组是不行的,因为a1数组里面装的是int类型

                   Object[]obj4 = a3;//可以,object数组中装的是int[] ,而int[]的父类型就是object

                   Object[]obj5 = s1;

                   

                   System.out.println(a1);

                   System.out.println(s1);

                   

                   System.out.println(Arrays.asList(a1));

                   System.out.println(Arrays.asList(s1));

                   

 

                   printObject(s1);

                   printObject("xyz");

                   

         }

         privatestatic void printObject(Object obj) {

                   Classclazz = obj.getClass();

                   if(clazz.isArray()){

                            intlen = Array.getLength(obj);

                            for(inti = 0 ;i<len;i++){

                                     System.out.println(Array.get(obj,i));

                            }

                   }else{

                            System.out.println(obj);

                   }

                   

         }

         //非常有用的一个代码

         privatestatic void changeStringValue(Object obj) throws Exception {

                   Field[]fields = obj.getClass().getFields();

                   for(Fieldfield : fields)

                   {

                            if(field.getType()== String.class)

                            {

                                     StringoldValue = (String) field.get(obj);

                                     StringnewValue = oldValue.replace('b', 'a');

                                     field.set(obj,newValue);

                            }

                   }

         }

 

}

 

class TestArguments{

         publicstatic void main(String[] args){

                   for(Stringarg : args){

                            System.out.println(arg);

                   }

         }

}

ReflectTest2.java

package cn.itcast.day1;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Properties;

public class ReflectTest2 {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		
		//InputStream ips = new FileInputStream("config.propertise");
		
		//用类加载器加载文件
		//InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.propertise");//不能加斜扛“/”cn/itcast/day1/config.propertise
		InputStream ips = ReflectTest2.class.getResourceAsStream("config.propertise");
		Properties props = new Properties();
		props.load(ips);
		ips.close();
		
		String className = props .getProperty("className");
		Collection collections = (Collection) Class.forName(className).newInstance();
		
		//Collection collections = new HashSet();
		ReflectPoint pt1 = new ReflectPoint(3,3);
		ReflectPoint pt2 = new ReflectPoint(5,3);
		ReflectPoint pt3 = new ReflectPoint(3,3);
		
		collections.add(pt1);
		collections.add(pt2);
		collections.add(pt3);
		collections.add(pt3);
		
		System.out.println(collections.size());
	}

}

ReflectPoint.java

package cn.itcast.day1;

import java.util.Date;

public class ReflectPoint {
		private int x;
		public int y;
		private Date birthday = new Date();
		
		public Date getBirthday() {
			return birthday;
		}
		public void setBirthday(Date birthday) {
			this.birthday = birthday;
		}
		String str1 = "abc";
		String str2 = "basketball";
		String str3 = "itcast";
		
		public ReflectPoint(int x, int y) {
			super();
			this.x = x;
			this.y = y;
		}
		public String toString()
		{
			return str1+":"+str2+":"+str3;
		}
		public int getX() {
			return x;
		}
		public void setX(int x) {
			this.x = x;
		}
		public int getY() {
			return y;
		}
		public void setY(int y) {
			this.y = y;
		}
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + x;
			result = prime * result + y;
			return result;
		}
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			ReflectPoint other = (ReflectPoint) obj;
			if (x != other.x)
				return false;
			if (y != other.y)
				return false;
			return true;
		}
		
}

 

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

抱歉!评论已关闭.