码迷,mamicode.com
首页 > 其他好文 > 详细

JDK1.5的新特性(2):反射

时间:2015-04-09 23:48:12      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:


关于Java基础的文章,我觉得写得还可以,以前发在了我其它的博客了,肯定是原创,现在再分享给大家出来。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



 一、概述


在总结java基础的博客里有简单的写到反射,这里再来深入的理解。http://blog.csdn.net/jin870132690/article/details/41958937

1,定义

首先的问题是什么是反射?百度百科给出的定义是这样的:

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;

这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

用我自己的话简而言之就是,程序运行时能操纵类的各种成分。


2,反射的基石--class类

java是完全面向对象的语言,在java中万物皆对象,比如男人和女人都可以属于Person类,那么众多的java类是不是也可以用一个类表示呢?

在java中就用一个名为Class的类来表示。


 二,获取Class类的三种方式


a,类名.class 

b,对象.getClass()

c,Class.forName("类名")

<div style="text-align: left;">	public static void main(String[] args) throws ClassNotFoundException {</div>		Date d = new Date();
		System.out.println(Date.class);\\a,类名.class 
<div style="text-align: left;">		System.out.println(Class.forName("java.util.Date"));\\c,Class.forName("类名")</div>		System.out.println(d.getClass());\\b,对象.getClass()
<div style="text-align: left;">	}</div>

 三,获取构造方法


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

a,得到某一个构造方法

Class clazz = Class.forName("java.lang.String");

Constructor con = clazz.getConstructor(byte[].class);//得到某一个构造函数

b,得到全部的构造方法

Constructor[] cons = clazz.getConstructors();//得到全部构造函数


 四,创建实例对象

使用Constructor.newInstance()方法

1,步骤

a,获取class类

b,获取Gonstructor构造方法

c,调用newInstance()方法.

<div style="text-align: left;">//a,获取class类</div><div style="text-align: left;">		Class clazz = Class.forName("jinfulin.b.bean");  </div>		//b,获取Gonstructor构造方法
<div style="text-align: left;">		Constructor cons = clazz.getConstructor(String.class,int.class);  </div>		//c,调用newInstance()方法.
<div style="text-align: left;">        Object obj = cons.newInstance("sf",21);  </div>


2,对于无参数构造函数可以简写,但是从底层调用上来看本质是一样的.

<div style="text-align: left;">  Class clazz = Class.forName("jinfulin.p.bean.Person");  </div><div style="text-align: left;">        Object obj = clazz.newInstance();//创建一个新的无参的实例  </div>

 五、成员变量的反射

1,方法

Field getField(String s);//只能获取公有和父类中公有

Field getDeclaredField(String s);//获取该类中所有的成员变量,包括私有

setAccessible(true);//对私有字段的访问取消权限检查。暴力访问。 

2,举例

<div style="text-align: left;">		//获取字段(属性)</div><div style="text-align: left;">		PointDemo pd = new PointDemo(3,2);</div><div style="text-align: left;">		Field field1 = pd.getClass().getField("x");</div>		Object o1 = field1.get(pd);
<div style="text-align: left;">		System.out.println(o1);</div>//		field1.set(o1, 12);
		
<div style="text-align: left;">		Field field2 = cls2.getDeclaredField("y");</div>		Object o2 = cls2.newInstance();
<div style="text-align: left;">//		Constructor con2 = cls2.getConstructor(int.class,int.class);</div>		field2.setAccessible(true);//暴力反射
		field2.set(o2, 12);
<div style="text-align: left;">		System.out.println(field2.get(o2));</div>

3,高级应用举例

-- 运用反射,将PointDemo类中的字符串中的所有字符替b换为a.

<div style="text-align: left;">/**</div><div style="text-align: left;">	 * 运用反射,将PointDemo类中的字符串中的某一个字符替换掉.</div>	 * @throws Exception 
	 */
<div style="text-align: left;">	private static void changeStringValue() throws Exception {</div>		Class cls = Class.forName("cn.jinfulin.day1.Reflect.PointDemo");
<div style="text-align: left;">		for(Field field : fields){</div>		Object obj = cls.newInstance();
		Field[] fields = cls.getFields();
<div style="text-align: left;">				String newString = oldString.replace('b', 'a');</div>			if(field.getType() == String.class){
				String oldString = (String) field.get(obj);
<div style="text-align: left;">	}</div>				field.set(obj, newString);
				
			}
		}
<div style="text-align: left;">		System.out.println(obj);</div>


 六、成员方法的反射


1,方法

        Method[] getMethods();//只获取公有的和父类中的方法。

        Method[] getDeclaredMethods();//获取本类中包含私有。

        Method   getMethod("方法名",参数.class);

        Object invoke(Object obj ,参数);//调用方法

        如果方法是静态,invoke方法中的对象参数可以为null。

比如

<div style="text-align: left;"><span style="white-space:pre">	</span>public static void main(String[] args) throws Exception {</div><span style="white-space:pre">		</span>
<div style="text-align: left;"><span style="white-space:pre">		</span>Object obj = clazz.newInstance();</div><span style="white-space:pre">		</span>Class clazz = Class.forName("java.util.Date");
<div style="text-align: left;"><span style="white-space:pre">	</span>    Object returnVaule=me.invoke(obj, null);</div><span style="white-space:pre">	</span>    Method me=clazz.getMethod("toString", null);  
<span style="white-space:pre">	</span>    System.out.println(returnVaule);      
<div style="text-align: left;"><span style="white-space:pre">	</span>}    </div>


2,举例:利用反射的方法调用charAt()方法

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

        2)反射方式:

<div style="text-align: left;">                                  Method charAtMethod =Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);</div><div style="text-align: left;">                                  charAtMethod.invoke(str,1);//调用方法</div>


3,用反射执行某个方法中的main方法

java中main方法的参数是一个数组,比如String [] args

但是由于java要兼容1.4版本,直接调用会将数组打散成单独的参数。

解决办法:

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

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

<div style="text-align: left;">	public static void main(String[] args) throws Exception {</div>		
		Class clazz = Class.forName("Ceshi.Demo.CeshiDemo");
<div style="text-align: left;">	    Method mainMethod=clazz.getMethod("main", String[].class);  </div>		Object obj = clazz.newInstance();
<div style="text-align: left;">	    System.out.println(returnVaule);      </div>	    Object returnVaule=mainMethod.invoke(obj, (Object)new String[]{});
<div style="text-align: left;">	}</div>


 七、数组中的反射

基本数据类型的一维数组可以当做Object类型使用,不能当做Object[]类型使用,

非基本数据类型的一维数组,既可以当做Object类型使用, 又可以当做Object[]使用。

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

        Array.getLength(Object obj);//获取数组的长度

        Array.get(Object obj,int x);//获取数组中的元素


<div style="text-align: left;">	/**</div><div style="text-align: left;">	 * 数组的反射</div>	 */
<div style="text-align: left;">	private static void printObject(Object obj) {</div>		Class clazz = obj.getClass();
<div style="text-align: left;">			int len = Array.getLength(obj);</div>		if(clazz.isArray()){//如果是数组,就分行打印
<div style="text-align: left;">				System.out.println(Array.get(obj, i));</div>			for (int i = 0; i <len; i++) {
				
			}
		}else{//如果不是就直接打印
<div style="text-align: left;">	}</div>			System.out.println(obj);
<div style="text-align: left;">		}</div>


 八、反射的作用:实现框架

1,概述

框架就像房子,而我们写的类就相当于给房子做装修。

 我们在写框架的时候,调用的类还未出现,那么,框架无法知道要被调用的类名,所以在程序中无法直接new其某个类的实例对象,而要用反射来做。

2,工具类与框架区别

工具类被用户类调用,

而框架是调用用户提供的类。

3,四种加载配置文件方法

a,普通方式

FileInputStream in = new FileInputStream("config.properties");

b,类加载器,全写

InputStream in = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/jinfulin/day1/Reflect/config.properties");

c,目录在类文件中,简写(在Java所在文件夹中会自动在类文件夹中创建相同一份)

InputStream in = ReflectTest2.class.getResourceAsStream("config.properties");

d,目录在其它包中,加/回到根目录下在找

InputStream in = ReflectTest2.class.getResourceAsStream("/cn/jinfulin/day1/config/config.properties");

4,举例

<div style="font-family: Arial; font-size: 14px; line-height: 26px; text-align: left;">package cn.jinfulin.day1.Reflect;</div><span style="font-family:Arial;"><span style="font-size: 14px; line-height: 26px;">
import java.io.InputStream;
</span></span><div style="font-family: Arial; font-size: 14px; line-height: 26px; text-align: left;">import java.util.Properties;</div><span style="font-family:Arial;"><span style="font-size: 14px; line-height: 26px;">import java.util.Collection;

public class ReflectTest2 {
</span></span><div style="font-family: Arial; font-size: 14px; line-height: 26px; text-align: left;">	public static void main(String[] args) throws Exception {</div><span style="font-family:Arial;"><span style="font-size: 14px; line-height: 26px;">	//仿照框架,用反射
		
		//1,读取配置文件中的内容
			//1.1源:键值对配置文件
</span></span><div style="font-family: Arial; font-size: 14px; line-height: 26px; text-align: left;">//		FileInputStream in = new FileInputStream("config.properties");</div><span style="font-family:Arial;"><span style="font-size: 14px; line-height: 26px;">//			//1.2三种得到输入流的方法
		//a,普通方式
//		//b,类加载器,全写
</span></span><div style="font-family: Arial; font-size: 14px; line-height: 26px; text-align: left;">//		InputStream in = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/jinfulin/day1/Reflect/config.properties");</div><span style="font-family:Arial;"><span style="font-size: 14px; line-height: 26px;">		//c,目录在类文件中,简写(在Java所在文件夹中会自动在类文件夹中创建相同一份)
//		InputStream in = ReflectTest2.class.getResourceAsStream("config.properties");
		//d,目录在其它包中,加/回到根目录下在找
</span></span><div style="font-family: Arial; font-size: 14px; line-height: 26px; text-align: left;">		in.close();</div><span style="font-family:Arial;"><span style="font-size: 14px; line-height: 26px;">		InputStream in = ReflectTest2.class.getResourceAsStream("/cn/jinfulin/day1/config/config.properties");
		Properties pros = new Properties();
		pros.load(in);
		String className = pros.getProperty("className");
		System.out.println(className);
</span></span><div style="font-family: Arial; font-size: 14px; line-height: 26px; text-align: left;">		PointDemo pd2 = new PointDemo(5, 5);</div><span style="font-family:Arial;"><span style="font-size: 14px; line-height: 26px;">		//2,读取类文件的字节码
		Class cls1 = Class.forName(className);
		Collection collections = (Collection)cls1.newInstance();
		
		
		
//		Collection collections = new HashSet();
		//3,集合中添加元素
		PointDemo pd1 = new PointDemo(3, 3);
		PointDemo pd3 = new PointDemo(3, 3);
</span></span><div style="font-family: Arial; font-size: 14px; line-height: 26px; text-align: left;">}</div><span style="font-family:Arial;"><span style="font-size: 14px; line-height: 26px;">
		collections.add(pd1);
		collections.add(pd2);
		collections.add(pd3);
		collections.add(pd1);
		pd1.x = 12;
		collections.remove(pd1);
		System.out.println(collections.size());
	}
</span></span><div style="text-align: left;"><span style="font-family:Arial;"><span style="font-size: 14px; line-height: 26px;">
</span></span></div>




 九、最后


以前写过一篇关于反射的文章,为什么又单独的写一遍?因为我觉得反射比较重要,以后学到了框架更是少不了的用,本篇显然比上一篇写反射的文章要深入多了,但是还不够,因为这些东西都是老师讲给我听,我照葫芦画瓢做出来的,像这些复杂的知识,真正掌握要还需要实践中见识更多的变化与应用场景才行。











JDK1.5的新特性(2):反射

标签:

原文地址:http://blog.csdn.net/jinfulin/article/details/44967503

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!