------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
反射
反射技术:把Java类中的各种成分映射成相应的java类
具体实现:
其实就是动态加载一个指定的类(该类可以从配置文件获取),并获取该类中的所有的内容。而且将字节码文件封装成对象,
并将字节码文件中的内容都封装成对象,这样便于操作这些成员。简单说:反射技术可以对一个类进行解剖。
反射的好处:大大的增强了程序的扩展性。
反射的基本步骤:
1、获得Class对象,就是获取到指定的名称的字节码文件对象。
2、实例化对象,获得类的属性、方法或构造函数。
3、访问属性、调用方法、调用构造函数创建对象。
-------------------------------------------------------------------
获得Class对象的三种方式:
//前两种方式不利于程序的扩展,因为都需要在程序使用具体的类来完成。
1:通过每个对象都具备的方法getClass来获取。弊端:必须要创建该类对象,才可以调用getClass方法。
Person p = new Person();
Class clazz = p.getClass;
2:每一个数据类型(基本数据类型和引用数据类型)都有一个静态的属性class。弊端:必须要先明确该类。
Class clazz = Person.class;
3:使用的Class类中的方法,静态的forName方法。 //这种方式的扩展性最强,只要将类名的字符串传入即可。
// 根据给定的类名来获得用于类加载
String classname = "Person"; // 来自配置文件
Class clazz = Class.forName(classname); // 此对象代表Person.class
-------------------------------------------------------------------
创建指定类对象的两种方式(其实就是对象在进行实例化时的初始化方式):
1,调用空参数的构造函数:使用了Class类中的newInstance()方法。
2,调用带参数的构造函数:
(1)、获取指定参数列表的构造函数对象
(2)、通过该构造函数的对象的newInstance(实际参数) 进行对象的初始化。
一般情况下,被反射的类,内部通常都会提供一个公有的空参数的构造函数。
public class Person {
/**
* @param args
*/
private String name;
private int age;
Person()
{
super();
System.out.println("Person run");
}
Person(String name ,int age)
{
this.age = age;
this.name = name;
}
public static void staticShow()
{
System.out.println("static show run");
}
public void show(String name ,int age)
{
System.out.println("show run"+name+"--"+age);
}
public String toString()
{
return age+"--"+name;
}
public static void main(String[] args) {
}
}
import java.lang.reflect.Constructor;
public class Reflect_GetConstructor {
/**
* 通过指定的构造函数初始化对象
* 1、获取文件字节码对象
* 2、再获取给定的构造函数
* 3、通过构造函数初始化对象
*
*/
public static void main(String[] args) throws Exception {
String className = "Person";
Class clazz = Class.forName(className);
//该实例化对象的方法调用就是指定类中的空参数构造函数,给创建对象进行初始化.
Constructor constructor = clazz.newInstance();
//获取指定的构造器。获取Person类中两个参数String,int的构造函数的形参。
Constructor constructor = clazz.getConstructor(String.class,int.class);
//有了构造器对象后,通过构造器对象来初始化该类对象。
conn.newInstance("wangwu",21);
}
}
-------------------------------------------------------------------
import java.lang.reflect.Method;
public class Reflect_GetMethod {
/**
* 获取方法。
*
*/
public static void main(String[] args) throws Exception {
getMethodDemo();//非静态方法的调用
getMethodDemo2();//静态方法的调用
}
public static void getMethodDemo2() throws Exception {
String className = "Person";
Class clazz = Class.forName(className);
String methodName = "staticShow";
//无参数,所以为null
Method method = clazz.getMethod(methodName,null);
//该方法是静态的,可以用类名调用,所以为空。
method.invoke(null,null);
}
public static void getMethodDemo() throws Exception {
String className = "Person";
Class clazz = Class.forName(className);
String methodName = "show";
Method method = clazz.getMethod(methodName,String.class,int.class);
Object obj = clazz.newInstance();
method.invoke(obj, "wangwu",20);
}
}
-------------------------------------------------------------------
获取类中所有构造器:
String className = "Person";
Class clazz = Class.forName(className);
Constructor[] constructors = clazz.getConstructors();//只包含公共的构造函数
//constructors = clazz.getDeclaredConstructors();包含私有的构造函数
for(Constructor con : constructors)
{
System.out.println(con);
}
获取类中所有的方法:
Class clazz = Class.forName("Person");
Method[] methods = clazz.getMethods();//获取的是该类中的公有方法和父类中的公有方法。
//methods = clazz.getDeclaredMethods();获取本类中的方法,包含私有方法。
for(Method method : methods)
{
System.out.println(method);
}
-------------------------------------------------------------------
运行私有方法。
public static void method_3() throws Exception {
Class clazz = Class.forName("cn.itcast.bean.Person");
//想要获取私有方法。必须用getDeclearMethod();
Method method = clazz.getDeclaredMethod("method", null);
// 私有方法不能直接访问,因为权限不够。非要访问,可以通过暴力的方式。
method.setAccessible(true);//一般很少用,因为私有就是隐藏起来,所以尽量不要访问。
}
-------------------------------------------------------------------
import java.lang.reflect.Field;
public class Reflect_GetField {
/**
* 获取字段。
getXXX:获取的都是类中公共的成员。
getDeclaredXXX:获取本类已定义的成员。
*/
public static void main(String[] args) throws Exception {
getFieldDemo();
}
public static void getFieldDemo() throws Exception {
String className = "Person";
Class clazz = Class.forName(className);
//获取字段
String fieldName = "age";
//Field field = clazz.getField(fieldName); NoSuchFieldException,因为age是私有的,该方法获取的是公共字段。
//getDeclaredField()能访问私有的成员。
Field field = clazz.getDeclaredField(fieldName);
//对其进行值得设定,必须先有对象。
Object obj = clazz.newInstance();
//通过查找父类AccessiableObject的方法。setAccessiable(true);
field.setAccessible(true);//取消权限检查,暴力访问。
field.set(obj, 30);//IllegalAccessException字段是私有的。
}
}
-----------------------------------------------------------------------
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class FieldDemo {
/**
*将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"。
* 思路:
* 1、对象类型不明确,需要用到反射。
* 2、
* 步骤:
* 1、通过forName方法获取该对象的字节码对象。
* 2、用Field[]存储getFields()方法获得的该字节码对象中的所有类型的字段。
* 3、对获取到的所有字段进行迭代操作,用field.getType()==String.class判断该字段是否为String类型
* 4、get()
* 5、set()
*/
public static void main(String[] args) throws Exception {
//changeStringVaule();
//getMethod();
getMainMethod();
}
//调用任意对象main方法
public static void getMainMethod() throws Exception {
String className = "test";
Class clazz = Class.forName(className);
//Object obj = clazz.newInstance();
Method method = clazz.getMethod("main", String[].class);
//method.invoke(null,new Object[]{new String[]{"111"}});
method.invoke(null,(Object)new String[]{"111"});
}
public static void getMethod() throws Exception {
//Method method = String.class.getMethod("charAt", int.class);
String className = "test";
Class clazz = Class.forName(className);
Object obj = clazz.newInstance();
Method method = clazz.getMethod("show",null);
method.invoke(obj);
}
public static void changeStringVaule() throws Exception {
//给我一个类名
String className = "test";
//通过该类名,获取该类名的字节码对象,并对该字节码对象进行初始化。
Class clazz = Class.forName(className);
//获取该字节码对象对应的实例,这句话相当于 test t1 = new test();
Object obj = clazz.newInstance();
//获取字节码对象的所有字段。
Field[] fields = clazz.getFields();
//对字节码对象中的字段进行迭代。
for (Field field : fields) {
//if(field.getType().equals(String.class))
if(field.getType()==String.class)
{
//返回指定对象上此 Field 表示的字段的值。获取的是obj这个对象的String类型的变量。
String oldVaule = (String)field.get(obj);
String newVaule = oldVaule.replace('b', 'a');
//设置obj这个对象的新字符串。将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
field.set(obj, newVaule);
System.out.println(newVaule);
}
}
System.out.println(new test());
}
}
public class test {
/**
* @param args
*/
public String str1 = "ball";
public String str2 = "basktball";
public test(){}
public test(String str1, String str2) {
super();
this.str1 = str1;
this.str2 = str2;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
show();
}
@Override
public String toString() {
return str1+"--"+str2;
}
public static void show()
{
System.out.println("show run");
}
}
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------