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

关于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>

九、最后

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

时间: 2024-10-25 10:53:27

JDK1.5的新特性(2):反射的相关文章

JDK1.5的新特性(1)

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

JDK1.5的新特性:javabean、注解类、类加载器

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

JAVA JDK1.5-1.9新特性

JAVA JDK1.5-1.9新特性 1.5 1.自动装箱与拆箱: 2.枚举(常用来设计单例模式) 3.静态导入 4.可变参数 5.内省 1.6 1.Web服务元数据 2.脚本语言支持 3.JTable的排序和过滤 4.更简单,更强大的JAX-WS 5.轻量级Http Server 6.嵌入式数据库 Derby 1.7 1,switch中可以使用字串了 2.运用List tempList = new ArrayList<>(); 即泛型实例化类型自动推断 3.语法上支持集合,而不一定是数组 4

Day07 jdk5.0新特性&Junit&反射

day07总结 今日内容 MyEclipse安装与使用 JUnit使用 泛型 1.5新特性 自动装箱拆箱 增强for 静态导入 可变参数方法 枚举 反射 MyEclipse安装与使用(yes) 安装MyEclipse 先安装了JDK ? MyEclipse介绍 ? MyEclipse是Eclipse的一个插件: MyEclipse是需要花钱的: MyEclipse官网不在欢迎中国人登录: ? MyEclipse使用 ? 1 创建项目 选择工作空间: 工作空间路径不能有空格和中文: 工作空间以班名

多线程(JDK1.5的新特性互斥锁)(掌握)

多线程(JDK1.5的新特性互斥锁)(掌握)1.同步·使用ReentrantLock类的lock()和unlock()方法进行同步2.通信·使用ReentrantLock类的newCondition()方法可以获取Condition对象·需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法·不同的线程使用不同的Condition, 这样就能区分唤醒的时候找哪个线程了举例: public static void main(String[] args) { f

黑马程序员——java高新---JDK1.5新特性和反射

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.JDK1.5新特性 ——>静态导入 import和import static之间的区别: 1.import是导入一个类或某个包中所有的类. 2.import static是导入一个类中的某个静态成员或所有的静态成员. 注意: 1.当导入的两个类中有同名成员时,需要在成员前加上相应的类名. 2.当类名重名时,需要指定具体的包名. 3.方法重名时,需要指定具体所属的对象或者类. 代码示例: 1

黑马程序员——java高新技术(新特性、反射、泛型)

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- java高新技术 第一部分——JDK1.5新特性 1.增强for循环 格式: for(元素类型 变量名 : Collection集合 & 数组 ) { }//增强for循环括号里写两个参数,第一个是声明一个变量,第二个就是需要迭代的容器 高级for循环和传统for循环的区别: 高级for循环在使用时,必须要明确被遍历的目标.这个目标,可以是Collection集合或者数组,如果遍历Collec

jdk1.5-1.10新特性

从网上搜集摘录的jdk特性,在这里记录下来以便自我学习. jdk5新特性    1.自动装箱和拆箱    2.枚举    3.静态导入    4.可变参数    5.內省       是Java语言对Bean类属性.事件的一种缺省处理方法.例如类A中有属性那么,那我们可以通过getName,setName来得到其值或者设置新的值.通过getName/setName来访问name属性,这就是默认的规则.Java中提供了一套API用来访问某个属性的getter,setter方法,通过这些API可以使

jdk1.8排序新特性

import java.util.Collections;import java.util.List;import java.util.ArrayList;import java.util.Comparator; public class Java8Tester { public static void main(String args[]){ List<String> names1 = new ArrayList<String>(); names1.add("Googl