这个java反射的练习,主要包含了反射的构造函数,属性,方法的调用,main方法的调用,以及一个简单的实战练习从文件中读取,并操作类。(用的是junit测试的,没有使用main方法的调用方式)
Person类:
package cn.wwh.www.reflect;
/**
*类的作用:纯粹是一个实体类包含属性和方法的测试类
*
*
*@author 一叶扁舟
*@version 1.0
*@创建时间: 2014-7-20 上午10:18:59
*/
public class Person {
private String name ;
private int age;
private String sex;
// 空的构造函数
public Person() {
System.out.println("不带参数的构造函数");
}
/**
* 带参数的构造函数
* @param name 姓名
* @param age 年龄
* @param sex 性别
*/
public Person(String name, int age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
System.out.println("带参数的构造函数");
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
/**
* @return the sex
*/
public String getSex() {
return sex;
}
/**
* @param sex the sex to set
*/
public void setSex(String sex) {
this.sex = sex;
}
public void show(){
System.out.println("无参数的show()方法");
}
public void show(String str){
System.out.println("带参数的show()方法"+str);
}
private String eat(){
return "我很能吃!";
}
public void showInfo(String name, int age){
System.out.println("我的名字是:"+name+"\t\t年龄:"+age);
}
public static void main(String[] args) {
System.out.println("main方法中-------->");
for (String string : args) {
System.out.print(string+"\t\t");
}
}
}
文件person.properties(是testExemple需要的文件):
className = cn.wwh.www.reflect.Person
methodName = show
案例的代码(Demo1.java):
package cn.wwh.www.reflect;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
import org.junit.Test;
/**
*类的作用:反射的练习
*
*
*@author 一叶扁舟
*@version 1.0
*@创建时间: 2014-7-20 上午08:57:04
*/
public class Demo1 {
/**
* 对于反射而言一般都要操作最多的是:构造函数,字段,方法
* 1.创建class对象的三种方式:
* (1)用类.class();
* (2)用对象.getClass();
* (3)用class.forName();的方式
* @throws Exception
*
*
*/
@Test
public void testGetClass() throws Exception {
Class clazz = String.class;
System.out.println("String.class:" + clazz);// 输出结果:String.class:class java.lang.String
//对象.getClass();
Class clazz1 = new String().getClass();
System.out.println("对象.getClass():"+clazz1);
Class clazz2 = Class.forName("java.lang.String");
System.out.println("forName():"+clazz2);
/**
* 输出的结果:
* String.class:class java.lang.String
对象.getClass():class java.lang.String
forName():class java.lang.String
*/
}
// 通过反射得到构造函数
@Test
public void testGetConstructor() throws Exception{
// 1.获得class 对象
Class classPerson = Class.forName("cn.wwh.www.reflect.Person");
Class classPerson1 = Class.forName("cn.wwh.www.reflect.Person");
// 2.获得对应的构造器
// (1)获取Person对象的所对应的类的全部的public的构造器
Constructor[] con = classPerson.getConstructors();
System.out.println(con);
System.out.println("-------------------------->");
for (Constructor constructor : con) {
System.out.println("constructor:"+constructor);
}
// (2).获取person对象所对应类的全部构造器
Constructor[] persons =
classPerson.getDeclaredConstructors();
System.out.println("person:"+persons);
// 3.(1)获取带参数的构造函数
Constructor conPerson1 = classPerson1.getConstructor(String.class,int.class,String.class);
// (2)获取无参数的构造函数
Constructor conPerson2 = classPerson1.getConstructor(null);
// 4.(1)创建一个带参数的实例
Person person1 = (Person) conPerson1.newInstance("一叶扁舟",20,"男");
// (2)创建无参数的实例
Person person2 = (Person) conPerson2.newInstance(null);
// 通过实例对象调用show()方法
person1.show("一叶扁舟");
person2.show();
}
//通过反射获取私有属性
@Test
public void testGetPrivateField() throws Exception{
// 1.获取Class对象
Class classPerson = Class.forName("cn.wwh.www.reflect.Person");
// 2.获取构造函数
Constructor conPerson = classPerson.getConstructor(null);
// 3.创建一个实例对象
Person person = (Person) conPerson.newInstance(null);
Field name = classPerson.getDeclaredField("name");
// 设置私有属性可以访问
name.setAccessible(true);
name.set(person,"一叶扁舟");
System.out.println("名字:"+person.getName());
}
// 通过反射获取方法的调用
@Test
public void testGetMethod() throws Exception{
Class classPerson = Class.forName("cn.wwh.www.reflect.Person");
Constructor conPerson = classPerson.getConstructor(null);
Person person = (Person) conPerson.newInstance(null);
Method me = classPerson.getDeclaredMethod("eat", null);
// 私有的方法要设置可访问
me.setAccessible(true);
me.invoke(person, null);
// 调用public带可变参数的方法
Method method = classPerson.getMethod("showInfo", String.class, int.class);
method.invoke(person, "一叶扁舟",20);
}
// 通过反射获取main方法:
@Test
public void testGetMain() throws Exception{
Class classPerson = Class.forName("cn.wwh.www.reflect.Person");
Constructor conPerson = classPerson.getConstructor(null);
Person person = (Person) conPerson.newInstance(null);
// 获取main方法
Method method = classPerson.getDeclaredMethod("main", String[].class);
/**
* 特别要注意:
* 在反射main方法时,编译器会将数组自动拆分,取第一个值
* 对此一般有两种方案
*/
// 第一种方案:
// method.invoke(person, (Object)new String[]{"一夜扁舟","21","男"});
// 第二种方案:
method.invoke(person,new Object[]{new String[]{"一夜扁舟","21","男"}});
}
// 用反射从文件中读取权限类名,然后调用方法
@Test
public void testExemple() throws Exception{
// 读取文件中的内容
Properties properties = new Properties();
InputStream is = new FileInputStream("src/cn/wwh/www/reflect/person.properties");
properties.load(is);
// 注意:这个必须要trim()一下,目的是要将文件读取时的空格给干掉
String className = properties.getProperty("className").trim();
String methodName = properties.getProperty("methodName").trim();
// 利用反射,操作文件中的类
Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor(null);
// constructor.setAccessible(true);
Method method = clazz.getDeclaredMethod(methodName, null);
method.setAccessible(true);
method.invoke(constructor.newInstance(null),null);
/**
* 特别要注意:
* 如果clazz.getDeclaredMethod(methodName, null)中第二个参数为空,则method.invoke()中
* 第二个参数也需要为空,即调用的methodName中无参数的方法
* 如果clazz.getDeclaredMethod(methodName, null)中第二个参数为String.class,则method.invoke()
* 中第二个参数必须为Object,哪怕为(Object)null也是必须的,此时调用的是methodName中有参数的方法
*
*/
}
}