黑马程序员---java反射详解

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


反射机制的作用:

              1,反编译:.class-->.java

              2,通过反射机制访问java对象的属性,方法,构造方法等;

         

。反射可以实现反编译功能,当一个 Xxx.java 源文件被编译后生成 Xxx.class 文件 ,可以通过反射来获得该 Xxx.class 文件的
Constructor ,Field , Method , Modifier(修饰符), 等。 

。在 Class 类中的 newInstance() 方法 会得到一个对象实例, 例: Class c = Class.forName("com.kingowe.Person") ;
Object o = c.newInstance() ; 会得到一个 Person 类的实例对象, 使用 newInstance() 方法 会调用 Person 类
的无参数构造方法,所以必须保证该类有 无参数构造方法

。实例化 Class 类对象的三种方法 : 1. Class.forName("com.kingowe.Person")     2. 类名.class 3.对象.getClass()   代码如下:


package com.kingowe ;
public class Person{
	private String name ;
	private int age ;
	{
		System.out.println("Person类 普通构造块") ;
	}

	static{
		System.out.println("Person类 static构造块") ;
	}
	public void setName(String name)	{
		this.name = name ;
	}
	public String getName()	{
		return this.name ;
	}
	public void setAge(int age)	{
		this.age = age ;
	}
	public int getAge()	{
		return this.age ;
	}
	public String toString() {
		return "姓名:"+this.name+"年龄:"+this.age ;
	}
}
public class ReflectTest1{
	public static void main(String[] args)throws Exception {  // 使用 forName()  方法会抛出异常	
		Person p = new Person() ;
		System.out.println(p.getClass().getName()) ;//得到对象所在的类 输出:com.kingowe.Person
							  // 通过 对象p 得到 类 的信息
		Class<?> c1 = null ;
		Class<?> c2 = null ;
		Class<?> c3 = null ;

		//forName()方法: static Class<?> forName(String className) 
		c1 = Class.forName("com.kingowe.Person") ;   
		/* 
		   使用 forName()参数是完整的类名,c1 引用指向内存中的对象,该对象代表的是 Person 整个类
		   调用 forName() 方法时 会将参数中的类进行【加载】 (如:在Person类中定义一个 
			static{ 
				System.out.println("kingowe");
			}
		    初始化块,在执行到 forName() 方法时 会输出 kingowe   注意: 在类 加载 时只会调用 static 初始化块) ,  
		   使用 Xxx.class 这种方式 不会加载该类
		*/
		c2 = new Person().getClass() ;	//对象.getClass()  该方法 extends Object

		c3 = Person.class ;	// 类.class  c2  c3  同 c1 一样 , 使用这种方法 在执行时不会加载 该调用类

		System.out.println(c1.getName()) ;  //Class类中方法: String getName() 
		System.out.println(c2.getName()) ;
		System.out.println(c3.getName()) ;

		System.out.println(c1 == c2) ;  //  输出 :  true
		System.out.println(c2 == c3) ;  //  输出 :  true    输出结果表示 c1 c2 c3 三个变量都指向同一个引用
	}
}

输出结果:

com.kingowe.Person
com.kingowe.Person
com.kingowe.Person
com.kingowe.Person

!*!*!*! 代码详解:  在以上代码中 如果同时使用 forName()  和 .class 这两种方式, 类只会加载一次,在执行完
!*!*!*!   c2 = new Person().getClass() ;  这行代码后 输出结果: Person类 static构造块 \r\n Person类 普通构造块
!*!*!*!



》》--》》   反射  +  IO   +   Properties


【配置文件】
dbinfo.properties 文件内容:
kingowe=99
kongchao:89
user kongchao
className=java.util.Date
//  key value 之间的连接符可以是 “:”“ ” “=”  如果有这种情况 user=kong:chao 
//  则按三个符号中首次出现的为 key value 分隔符
//  【注意】:java的配置文件格式 只需要键值之间的连接符,不需要其他符号, 一对键值结尾
//  不需要加结束符号, 值也不需要用双引号

import java.io.* ;
import java.util.* ;
public class IOProperties
{
	public static void main(String[] args) throws IOException, Exception
	{
		  // 会抛出异常
		FileInputStream fis = new FileInputStream("dbinfo.properties") ;
		Properties p = new Properties() ;
		  // public void load(InputStream inStream)
		p.load(fis) ; // 会 抛出异常
		fis.close() ; //记得关闭流文件
		  //  String getProperty(String key) 
		String value1 = p.getProperty("kingowe") ; //会根据文件 dbinfo.properties中的
				// key-value 中的 key值来取出对应的value值
		String value2 = p.getProperty("kongchao") ;
		String value3 = p.getProperty("user") ;
		String value4 = p.getProperty("className") ;
		System.out.println(value1) ;
		System.out.println(value2) ;
		System.out.println(value3) ;
		System.out.println(value4) ;
		
		// 通过反射机制来创建对象 使用dbinfo.properties 中的 key className 对应的 value
		String className = p.getProperty("className") ;
		Class c = Class.forName(className) ;
		// 创建对象
		Object o = c.newInstance() ;
		System.out.println(o) ;	  // Tue Apr 08 23:38:29 CST 2014
		
	}
}

》》 -- 》》Field:

实例代码:

import java.lang.reflect.* ;
public class GetClassxx
{
	public static void main(String[] args) throws Exception
	{
		// 获取整个类
		Class c1 = Class.forName("Demo") ; // 这里forName() 参数可以为任意类
		// 获取Field[]
		Field[] fs1 = c1.getFields() ;//使用该方法 只能获得 public 修饰的 Field
		System.out.println(fs1.length) ; // 1
		System.out.println(fs1[0].getName()) ;// 取得该 Field 的name

		Field[] fs2 = c1.getDeclaredFields()  ; //此方法会获得所有Field
		System.out.println(fs2.length) ;
		for(int i=0; i<fs2.length; i++){
			//取得类型 public Class<?> getType()
			Class type = fs2[i].getType() ;
		 	System.out.println(type.getName()+"   "+ fs2[i].getName() + "   ") ;
			 // 【getName() 取得变量名:int age; 取得age】
<span style="white-space:pre">			</span>/*  输出: 
<span style="white-space:pre">			</span>1
<span style="white-space:pre">			</span>age
<span style="white-space:pre">			</span>3
<span style="white-space:pre">			</span>int   age
<span style="white-space:pre">			</span>java.lang.String   name
<span style="white-space:pre">			</span>boolean   flag
<span style="white-space:pre">			</span>注:也可以使用 type.getSimpleName()  得到 int String Boolean
<span style="white-space:pre">			</span>*/

		}				
		// 获取修饰符: int getModifiers()  
		for(int j=0; j<fs2.length; j++)
		{
			int n = fs2[j].getModifiers() ;
			// 【Modifier类 中的方法: static String toString(int mod) 】
			String m = Modifier.toString(n) ;
			System.out.println("修饰符:"+m) ;
		}
	}
}
》》 - -》》 Method
package com.kingowe.test;

import java.lang.reflect.Method;

public class Test {
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		
		Class<?> c = Class.forName("com.kingowe.test.Person"); 
		Method[] ms = c.getMethods();
		for(Method m : ms){
			String methodName = m.getName();
			System.out.println("方法名:" + methodName);
			if(methodName.startsWith("get")){
				m.invoke(c.newInstance());	
				// 【通过Method类,调用 Person 类中的getter方法(无参数)】
			}
			
			if(methodName.equals("setAge")){
				m.invoke(c.newInstance(), 21);  // 【调用有参数的方法时 为方法设置参数】
			}
			
			if(methodName.equals("setAgeAndName")){
				m.invoke(c.newInstance(), 20, "孔超");
			}
		}
	}

}







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值