`
ku_uga
  • 浏览: 46523 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

认识Java反射机制

阅读更多

认识Java反射机制

     在正常情况下,必须知道一个类才可以实例化对象,但是在Java中也通过一个对象来找到其所在的类的信息,那么这实际上是Class类的功能。

package zyz.demo;
class X{ };
public class GetClassDemo01{
	public static void main(String args[]){
		X x = new X() ;	// 实例化X类的对象
		System.out.println(x.getClass().getName()) ;	// 得到对象所在的类的完整名字
	}
};   
 结果:zyz.demo.X

 

 

 

 

 

实例化Class类型对象

实例化Class类型对象的方法有三种:

第一种:通过forName()方法

第二种:类.class

第三种:对象.getClass()

 

package zyz.demo;
class X{
};
public class GetClassDemo02{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 指定泛型
		Class<?> c2 = null ;		// 指定泛型
		Class<?> c3 = null ;		// 指定泛型
		try{
			// 以下的操作形式是在开发中最常用的一种形式
			c1 = Class.forName("org.lxh.demo15.getclassdemo.X") ;
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		c2 = new X().getClass() ;	// 通过Object类中的方法实例化
		c3 = X.class ;	// 通过类.class实例化
		System.out.println("类名称:" + c1.getName());// 得到类的名称
		System.out.println("类名称:" + c2.getName());// 得到类的名称
		System.out.println("类名称:" + c3.getName());// 得到类的名称
	}
};

 

一旦可以实例化Class类之后,就可以进行反射的进一步操作。

 

1、实例化对象

class Person{
	private String name ;	// name属性
	private int age ;		// age属性
	public void setName(String name){
		this.name = name ;
	}
	public void setAge(int age){
		this.age = age ;
	}
	public String getName(){
		return this.name ;
	}
	public int getAge(){
		return this.age ;
	}
	public String toString(){	// 覆写toString()方法
		return "姓名:" + this.name + ",年龄:" + this.age  ;
	}
};
public class Demo01{
	public static void main(String args[]){
		Class<?> c = null ;		// 声明Class对象
		try{
			c = Class.forName("org.lxh.demo15.instancedemo.Person") ;
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Person per = null ;	// 声明Person对象
		try{
			per = (Person)c.newInstance() ;	// 实例化对象
		}catch(Exception e){
			e.printStackTrace() ;
		}
		per.setName("李兴华") ;		// 设置姓名
		per.setAge(30) ;				// 设置年龄
		System.out.println(per) ;	// 内容输出,调用toString()
	}
};

 

 

 

 

     通过以上的代码,可以发现,即使不使用关键字new对象也可以进行实例化操作,反射的作用。但是,在使用以上操作的时候有一点必须注意,在操作中类中必须存在无参构造方法。否则无法实例化。

 

     所以说,使用以上的方法实际上还是需要类中构造方法的支持,符合于对象的实例化需求。

如果要想调用有参,由必须按照以下的步骤进行:

1、通过Class类中的getConstructors()取得本类中的全部构造方法。

2、向构造方法中传递一个对象数组进去,里面包含了构造方法中所需的各个参数。

3、之后通过Constructor实例化对象

package org.lxh.demo15.instancedemo ;
import java.lang.reflect.Constructor ;	// 导入反射机制包
class Person{
	private String name ;	// name属性
	private int age ;		// age属性
	public Person(String name,int age){
		this.setName(name) ;
		this.setAge(age);
	}
	public void setName(String name){
		this.name = name ;
	}
	public void setAge(int age){
		this.age = age ;
	}
	public String getName(){
		return this.name ;
	}
	public int getAge(){
		return this.age ;
	}
	public String toString(){	// 覆写toString()方法
		return "姓名:" + this.name + ",年龄:" + this.age  ;
	}
};
public class InstanceDemo03{
	public static void main(String args[]){
		Class<?> c = null ;		// 声明Class对象
		try{
			c = Class.forName("org.lxh.demo15.instancedemo.Person") ;
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Person per = null ;	// 声明Person对象
		Constructor<?> cons[] = null ;
		cons = c.getConstructors() ;
		try{
			// 第一个数组
			per = (Person)cons[0].newInstance("李兴华",30) ;	// 实例化对象
		}catch(Exception e){
			e.printStackTrace() ;
		}
		System.out.println(per) ;	// 内容输出,调用toString()
	}
};

 

 

 

     但是,从实际角度看,如果要使用反射进行对象的实例化操作,最好在类中存在无参构造。

 

2、取得类所实现的全部接口

 

package org.lxh.demo15.classinfodemo ;
public class GetInterfaceDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Class<?> c[] = c1.getInterfaces() ;	// 以数组形式返回实现的全部接口
		for(int i=0;i<c.length;i++){
			System.out.println("实现的接口名称:" + c[i].getName()) ;	// 输出接口名称
		}
	}    
};
结果:实现的接口名称:org.lxh.demo15.China

 

3、取得父类

package org.lxh.demo15.classinfodemo ;
public class GetSuperClassDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Class<?> c2 = c1.getSuperclass() ;	// 取得父类
		System.out.println("父类名称:" + c2.getName()) ;
	}
};        
结果:父类名称:java.lang.Object

 

 

 

4、取得类中的全部构造方法

 

package org.lxh.demo15.classinfodemo ;
import java.lang.reflect.Constructor ;	// 导入构造方法的包
public class GetConstructorDemo01{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Constructor<?> con[] = c1.getConstructors() ;	// 取得一个类中的全部构造
		for(int i=0;i<con.length;i++){
			System.out.println("构造方法:" + con[i]) ;	 // 输出构造,直接打印
		}   
}         	  
};   
结果:
构造方法:public org.lxh.demo15.Person()
构造方法:public org.lxh.demo15.Person(java.lang.String)
构造方法:public org.lxh.demo15.Person(java.lang.String,int)

  

 

 

     以上的操作确实取得了类中的构造方法,但是此时是通过对象直接打印取得的,肯定会调用Constructor类中的toString()方法。

     Constructor类中存在了以下的几个方法:

    取得修饰符:public int getModifiers()

    取得方法名称:public String getName()

    取得参数的类型:public Class<?>[] getParameterTypes()

package org.lxh.demo15.classinfodemo ;
import java.lang.reflect.Constructor ;	// 导入构造方法的包
public class GetConstructorDemo02{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Constructor<?> con[] = c1.getConstructors() ;	// 取得一个类中的全部构造
		for(int i=0;i<con.length;i++){
			Class<?> p[] = con[i].getParameterTypes() ;		// 得到构造方法中的全部参数
			System.out.print("构造方法:" ) ;	 // 输出构造,直接打印
			System.out.print(con[i].getModifiers() + " ") ;	// 得到修饰符
			System.out.print(con[i].getName()) ;	// 取得构造方法的名字
			System.out.print("(") ;
			for(int j=0;j<p.length;j++){
				System.out.print(p[j].getName() + " arg" + i) ;
				if(j<p.length-1){
					// 判断此是否是最后一个参数
					System.out.print(",");	// 输出“,”
				}
			}
			System.out.println("){}") ;
		}
	}
};

 

 

 

运行结果:

构造方法:1 org.lxh.demo15.Person(){}

构造方法:1 org.lxh.demo15.Person(java.lang.String arg1){}

构造方法:1 org.lxh.demo15.Person(java.lang.String arg2,int arg2){}

此时,在操作之后,发现,所有的修饰符变成了数字。需要还原修饰符,改写上面的代码

package org.lxh.demo15.classinfodemo ;
import java.lang.reflect.Constructor ;	// 导入构造方法的包
import java.lang.reflect.Modifier ;	// 导入构造方法的包
public class GetConstructorDemo03{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Constructor<?> con[] = c1.getConstructors() ;	// 取得一个类中的全部构造
		for(int i=0;i<con.length;i++){
			Class<?> p[] = con[i].getParameterTypes() ;		// 得到构造方法中的全部参数
			System.out.print("构造方法:" ) ;	 // 输出构造,直接打印
			int mo = con[i].getModifiers() ; // 得到所要的访问权限
			System.out.print(Modifier.toString(mo) + " ") ;	// 转换得到的修饰符
			System.out.print(con[i].getName()) ;	// 取得构造方法的名字
			System.out.print("(") ;
			for(int j=0;j<p.length;j++){
				System.out.print(p[j].getName() + " arg" + i) ;
				if(j<p.length-1){
					// 判断此是否是最后一个参数
					System.out.print(",");	// 输出“,”
				}
			}
			System.out.println("){}") ;
		}
	}
};

 

 

 

 运行结果:

构造方法:public org.lxh.demo15.Person(){}

构造方法:public org.lxh.demo15.Person(java.lang.String arg1){}

构造方法:public org.lxh.demo15.Person(java.lang.String arg2,int arg2){}

 

5、取得类中的全部方法

package org.lxh.demo15.classinfodemo ;
import java.lang.reflect.Method ;	// 导入构造方法的包
import java.lang.reflect.Modifier ;	// 导入构造方法的包
public class GetMethodDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		Method m[] = c1.getMethods() ;	// 取得全部方法
		for(int i=0;i<m.length;i++){
			Class<?> r = m[i].getReturnType() ;	// 得到返回值类型
			Class<?> p[] = m[i].getParameterTypes() ;	// 取得全部参数的类型
			int xx = m[i].getModifiers() ;	// 得到修饰符
			System.out.print(Modifier.toString(xx) + " ") ;	// 输出修饰符
			System.out.print(r + " ") ;
			System.out.print(m[i].getName()) ;
			System.out.print("(") ;
			for(int j=0;j<p.length;j++){
				System.out.print(p[j].getName() + " " + "arg" + j) ;
				if(j<p.length-1){
					System.out.print(",") ;
				}
			}
			Class<?> ex[] = m[i].getExceptionTypes() ;	// 取出异常
			if(ex.length>0){ // 判断是否产生异常
				System.out.print(") throws ") ;
			}else{
				System.out.print(")") ;
			}
			for(int j=0;j<ex.length;j++){
				System.out.print(ex[j].getName()) ;
				if(j<p.length-1){
					System.out.print(",") ;
				}
			}
			System.out.println() ;
		}
	}
};

 

 

运行结果:

public void sayChina()

public class java.lang.String sayHello(java.lang.String arg0,int arg1)

public void setAge(int arg0)

public int getAge()

public class java.lang.String getName()

public void setName(java.lang.String arg0)

public final void wait() throws java.lang.InterruptedException

public final void wait(long arg0,int arg1) throws java.lang.InterruptedException,

public final native void wait(long arg0) throws java.lang.InterruptedException

public native int hashCode()

public final native class java.lang.Class getClass()

public boolean equals(java.lang.Object arg0)

public class java.lang.String toString()

public final native void notify()

public final native void notifyAll()

 

     在一般的开发工具中经常看见随笔提示功能,实际上此功能就是利用以上的程序完成的。

 

6、取得类中的属性

package org.lxh.demo15.classinfodemo ;
import java.lang.reflect.Field ;	// 导入构造方法的包
import java.lang.reflect.Modifier ;	// 导入构造方法的包
public class GetFieldDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;		// 声明Class对象
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化对象
		}catch(ClassNotFoundException e){
			e.printStackTrace() ;
		}
		{	// 本类属性
			Field f[] = c1.getDeclaredFields() ;	// 取得本类中的属性
			for(int i=0;i<f.length;i++){
				Class<?> r = f[i].getType() ;	// 得到属性类型
				int mo = f[i].getModifiers() ;	// 得到修饰符的数字
				String priv = Modifier.toString(mo) ; // 还原修饰符
				System.out.print("本类属性:") ;
				System.out.print(priv + " ") ;	
				System.out.print(r.getName() + " ") ;	// 得到属性类型
				System.out.print(f[i].getName()) ;	// 输出属性名称
				System.out.println(" ;") ;
			}
		}
		{	// 公共属性
			Field f[] = c1.getFields() ;	// 取得本类中的公共属性
			for(int i=0;i<f.length;i++){
				Class<?> r = f[i].getType() ;	// 得到属性类型
				int mo = f[i].getModifiers() ;	// 得到修饰符的数字
				String priv = Modifier.toString(mo) ; // 还原修饰符
				System.out.print("公共属性:") ;
				System.out.print(priv + " ") ;	
				System.out.print(r.getName() + " ") ;	// 得到属性类型
				System.out.print(f[i].getName()) ;	// 输出属性名称
				System.out.println(" ;") ;
			}
		}
	}
};

 

 

运行结果:

本类属性:private java.lang.String name ;

本类属性:private int age ;

公共属性:public static final java.lang.String NATIONAL ;

公共属性:public static final java.lang.String AUTHOR ;

 

7、通过反射调用类中的方法

    

package org.lxh.demo15.invokedemo ;
import java.lang.reflect.Method ;
public class InvokeSayChinaDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化Class对象
		}catch(Exception e){}
		try{
			Method  met = c1.getMethod("sayChina") ;	// 找到sayChina()方法
			met.invoke(c1.newInstance()) ;	// 调用方法
		}catch(Exception e){
			e.printStackTrace() ;
		}
	}
};

 

 

 

     如果现在要调用的方法中存在了参数,则必须设置参数的类型及内容。

package org.lxh.demo15.invokedemo ;
import java.lang.reflect.Method ;
public class InvokeSayHelloDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化Class对象
		}catch(Exception e){}
		try{
			Method  met = c1.getMethod("sayHello",String.class,int.class) ;	// 找到sayHello(String name,int age)方法
			String rv = null ;
			rv = (String)met.invoke(c1.newInstance(),"李兴华",30) ;	// 调用方法
			System.out.println(rv) ;
		}catch(Exception e){
			e.printStackTrace() ;
		}
	}
};

 

 

 

8、通过反射调用类setter及getter

     SetterGetter方法是一个标准的属性的访问方法,如果一个类的属性被封闭,则必须通过settergetter方法设置和取得,实际上此方法的操作之所以要这样规定,主要原因是由于反射机制可以给予支持的。

package org.lxh.demo15.invokedemo ;
import java.lang.reflect.Method ;
public class InvokeSetGetDemo{
	public static void main(String args[]){
		Class<?> c1 = null ;
		Object obj = null ;
		try{
			c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化Class对象
		}catch(Exception e){}
		try{
			obj = c1.newInstance() ;
		}catch(Exception e){}
		setter(obj,"name","李兴华",String.class) ;	// 调用setter方法
		setter(obj,"age",30,int.class) ;	// 调用setter方法
		System.out.print("姓名:") ;
		getter(obj,"name") ;
		System.out.print("年龄:") ;
		getter(obj,"age");
	}
	/**
		Object obj:要操作的对象
		String att:要操作的属性
		Object value:要设置的属性内容
		Class<?> type:要设置的属性类型
	*/

 

 

 

9、通过反射调用属性

     观察,以上的操作中是否需要类的settergetter方法支持呢?证明以上的操作调用与settergetter无关,但是为了保证程序的安全性,最好还是通过settergetter方法完成调用。

package org.lxh.demo15.invokedemo ;
import java.lang.reflect.Field ;
public class InvokeFieldDemo{
	public static void main(String args[]) throws Exception{
		Class<?> c1 = null ;
		Object obj = null ;
		c1 = Class.forName("org.lxh.demo15.Person") ;	// 实例化Class对象
		obj = c1.newInstance() ;
		Field nameField = null ;
		Field ageField = null ;
		nameField = c1.getDeclaredField("name") ;	// 取得name属性
		ageField = c1.getDeclaredField("age") ;	// 取得name属性
		nameField.setAccessible(true) ;	// 此属性对外部可见
		ageField.setAccessible(true) ;	// 此属性对外部可见
		nameField.set(obj,"李兴华") ;	// 设置name属性内容
		ageField.set(obj,30) ;			// 设置age属性内容
		System.out.println("姓名:" + nameField.get(obj)) ;
		System.out.println("年龄:" + ageField.get(obj)) ;
	}
};

 

 

 

10、通过反射操作数组

     反射机制不光只能用在类中,也可以应用在任意的引用数据类型上,当然,这就包含了数组,数组使用Array类完成。

     Class类中存在以下一个方法:

public Class<?> getComponentType()

 

分享到:
评论

相关推荐

    实战java反射机制-让你迅速认识java强大的反射机制

    NULL 博文链接:https://stephen830.iteye.com/blog/256723

    J2SE笔记讲解个人修订(1.1).docx

    5 JAVA反射机制 6 JAVA注解(ANNOTATION) 7 JAVA中的异常类 8 JAVA-SWING 9 观察者模式 10 内部类讲解 11 JAVA I/O流讲解 12 JAVA多线程 13 JAVA网络通信 14 JAVA类加载器CLASSLOADER 15 JAVA简单工厂...

    精通Java:JDK、数据库系统开发Web开发(实例代码)

    第8章 Java反射机制 第9章 数据结构与集合类 第3篇 图形用户界面 第10章 Java Swing(上) 第11章 Java Swing(下) 第12章 Applet网页小程序 第13章 图形编程 第14章 多媒体编程 第4篇 Java高级技术 第15章 字符串...

    Java开发详解.zip

    031501_【第15章:Java反射机制】_认识Class类笔记.pdf 031502_【第15章:Java反射机制】_Class类的使用笔记.pdf 031503_【第15章:Java反射机制】_反射应用——取得类的结构笔记.pdf 031504_【第15章:Java反射机制...

    深入理解Java类型信息(Class对象)与反射机制

    至于Java中出现RRTI的说法则是源于《ThinkinginJava》一书,其作用是在运行时识别一个对象的类型和类的信息,这里分两种:传统的”RRTI”,它假定我们在编译期已知道了所有类型(在没有反射机制创建和使用类对象时,...

    反射:认识反射、获取类

    在Java中,反射是一种机制,它允许程序在运行时获取和操作类的信息,包括类的构造器、字段、方法等。通过反射,我们可以在编译时期未知类的情况下,动态地操作类的成员。

    JAVA中级书籍

    反射机制;多线程;IO/NIO; 网络编程;常用数据结构和相关算法。 2、对面向对象的软件开发思想有清晰的认识、熟悉掌握常用的设计模式;设计模式;单例模式;工厂模式;代理模式;模板方法模式;责任链模式等。 3...

    java基础案例与开发详解案例源码全

    15.2 使用Java反射机制414 15.2.1 获取类型信息414 15.2.2 创建对象417 15.2.3 调用方法419 15.2.4 访问成员变量的值421 15.2.5 操作数组422 15.3 反射与动态代理424 15.3.1 静态代理424 15.3.2 动态代理426 15.4 本...

    JAVA面试题最全集

    描述反射机制的作用 62.如何读写一个文件? 63.在图形界面中,一个按钮如何处理鼠标点击事件? 64.在图形界面中,一个表格,如何实现编辑单元格时弹出下拉框? 65.如何加载图片? 66.什么是模态对话框? 67....

    Java核心技术精讲

    从重新认识反射的定义开始,了解JAVA的核心技术; 理解Java中9大内置Class实例; 详细介绍包名、类名、接口、继承、修饰符等内容; 深入理解List、Map、Set的实现机制以及原理 深入理解泛型的原理以及在日常工作...

    面向对象技术与UML课件及源代码-by 南邮-陈杨

    13.3通过反射机制访问对象 13.3.1如何实例化对象 13.3.2如何给成员变量赋值 13.3.3如何调用成员函数 13.4何时使用反射 13.5动态异常处理框架 13.5.1框架功能简介 13.5.2重要技术 13.5.3框架代码编写 13.5.4...

    Spring.3.x企业应用开发实战(完整版).part2

    3.2.3 Java反射机制 3.3 资源访问利器 3.3.1 资源抽象接口 3.3.2 资源加载 3.4 BeanFactory和ApplicationContext 3.4.1 BeanFactory介绍 3.4.2 ApplicationContext介绍 3.4.3 父子容器 3.5 Bean的生命周期 3.5.1 ...

    Spring3.x企业应用开发实战(完整版) part1

    3.2.3 Java反射机制 3.3 资源访问利器 3.3.1 资源抽象接口 3.3.2 资源加载 3.4 BeanFactory和ApplicationContext 3.4.1 BeanFactory介绍 3.4.2 ApplicationContext介绍 3.4.3 父子容器 3.5 Bean的生命周期 3.5.1 ...

    asp.net知识库

    利用反射实现ASP.NET控件和数据实体之间的双向绑定,并且在客户端自动验证输入的内容是否合法 asp.net报表解决方法 SQLDMO类的使用 SQL过程自动C#封装,支持从表到基本存储过程生成 使用SQLDMO控制 SQL Server 使用SQL...

Global site tag (gtag.js) - Google Analytics