------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, "孔超");
}
}
}
}