反射:就是把java类中的各种成分映射成相应的java类
反射一般有,对类的构造函数进行反射,对类中的成员变量进行反射,对类中的成员方法进行反射,对数组进行反射。
//获取Class对象的三种方法即获取类的字节码文件,以String类为例
class GetInstance
{
public static void main(String[] args)throws Exception
{
getClassIns();
isPrimitive();
}
public static void getClassIns()throws Exception
{
String str = "abc";
//第一种直接 类名.class 就是代表该类所对应的字节码文件,即class文件
Class c1 = String.class;
//通过所需类的对象调用getClass()方法,getClass()方法是Object类中的方法
Class c2 = str.getClass();
//通过Class类中的静态方法forName(String className),参数为该类所在的具体位置
Class c3 = Class.forName("java.lang.String");
System.out.println(c1==c2);
System.out.println(c1==c3);
}
//判断该类的字节码文件是否为基本数据类型的字节码文件
public static void isPrimitive()
{
System.out.println(int.class.isPrimitive());//true
System.out.println(Integer.class.isPrimitive());//false
System.out.println(int.class==Integer.TYPE);//true
//基本数据类型的包装类调用TYPE字段返回该类对应的基本数据类型
}
}
反射取出类中的构造函数:
getConstructor(parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
//获取类的一个具体的构造方法 如用反射的方法实现 new Integer("123") new Integer(new String("456"));
public static void getCon()throws Exception
{
//获取Integer类中带有String参数的构造方法
//Constructor con = Integer.class.getConstructor(String.class);
Constructor con = Class.forName("java.lang.Integer").getConstructor(String.class);
//将获取到的构造方法实例化,并按照要求往其中传入参数
//Integer in = (Integer)con.newInstance("123");
Integer in = (Integer)con.newInstance(new String("456"));
System.out.println(in);
}
反射取出类中的成员变量:
Field getDeclaredField(String name)
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
Field[] getDeclaredFields()
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
Object get(Object obj)
返回指定对象上此 Field 表示的字段的值
class GetField
{
public static void main(String[] args)throws Exception
{
getFie();
Demo d = new Demo(1,2);
System.out.println(d);
replaceFields(d);
System.out.println(d);
}
//获取一个类中的成员变量
public static void getFie()throws Exception
{
Demo d = new Demo(5,6);
//获取公共成员X字段,它是一个对象,并不是具体的值
Field fieldX = d.getClass().getField("x");
//获取指定对象上X字段对应的值
int x = (int)fieldX.get(d);
//获取声明过的字段
Field fieldY = d.getClass().getDeclaredField("y");
//将私有的字段暴露
fieldY.setAccessible(true);
int y = (int)fieldY.get(d);
System.out.println(y);
}
//用反射的方法将一个类中所有String类型的字段中的'a'改成'c'
public static void replaceFields(Object obj) throws Exception
{
Field[] fields = obj.getClass().getFields();
for (Field field : fields )
{
//取出指定类型的字段
if(field.getType()==String.class)
{
String value = (String)field.get(obj);
//替换值
String newValue = value.replace('b','a');
//System.out.println(newValue);
//将改变后的新值重新设置到指定对象的字段中
field.set(obj,newValue);
}
}
}
}
class Demo
{
public int x ;
private int y ;
public String a = "aabbccddaa";
public String b = "123aa33bb3tt";
public String c = "javadoc";
Demo(int x,int y)
{
this.x = x ;
this.y = y ;
}
public String toString()
{
return a+" "+b+" "+c ;
}
}
反射取出类中的成员方法:
Method getDeclaredMethod(name,parameterTypes)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
Method[] getDeclaredMethods()
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
Object invoke(Object obj, Object… args)
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
class GetMethod
{
public static void main(String[] args)throws Exception
{
getMain();
getMe();
}
//获取类中的方法,并调用 如String类中的indexOf(String str)
public static void getMe() throws Exception
{
String str = "abc";
Method method = String.class.getMethod("indexOf",String.class);
//indexOf指的是要获取的具体方法 String.class 指的是方法的参数类型,可以有多个参数
int in = (int)method.invoke(str,"b");//可以理解为是String类对象调用indexOf方法,参数是"b"
System.out.println(in);
}
//反射调用一个类中的main方法
public static void getMain() throws Exception
{
//Method method = Class.forName("ForDemo").getMethod("main",String[].class);
Method method = ForDemo.class.getMethod("main",String[].class);
//如果方法是静态的,则第一个参数为null,因为不需要对象调用
//method.invoke(null,new Object[]{new String[]{"12","23","34"}});
method.invoke(null,(Object)new String[]{"12","23","34"});
}
}
class ForDemo
{
public static void main(String[] args)
{
for (String arg : args )
{
System.out.println(arg);
}
}
}
对数组进行反射:
boolean isArray()
判定此 Class 对象是否表示一个数组类。
static Object get(Object array, int index)
返回指定数组对象中索引组件的值。
static int getLength(Object array)
以 int 形式返回指定数组对象的长度
class GetArr
{
public static void main(String[] args)throws Exception
{
String[] str = {"25","56","78"};
reflectArr(str);
String str1 = "256879";
reflectArr(str1);
int[] arr = {1,8,6,4,8};
reflectArr(arr);
}
//对数组进行反射,数组是引用数据类型,属于Object类
public static void reflectArr(Object obj) throws Exception
{
Class cla = obj.getClass();
//判断是否为数组
if (cla.isArray())
{
//通过对象获取数组的长度
int len = Array.getLength(obj);
for (int x=0;x<len ;x++ )
{
//获取数组中角标对应的值
System.out.println(Array.get(obj,x));
}
}
else
System.out.println(obj);
}
}
反射的应用:
用反射做一个简单的框架:如不使用具体的集合中的类,通过配置文件取出集合类并实现集合类的功能
思路:
1.写一个配置文件,用键值对的形式表示出具体的类的限定名
2.用Properties集合将集合与输入流相结合
3.取出键对应的值,即类的限定名
4.利用反射获取类并将其实例化,则可以取到具体的集合
5.对集合进行操作
import java.util.*;
import java.lang.reflect.*;
import java.io.*;
class ReflectTest
{
public static void main(String[] args) throws Exception
{
ReflectColl();
}
public static void ReflectColl() throws Exception
{
//和指定的文件相关联
InputStream in = new FileInputStream("Coll.properties");
Properties prop = new Properties();
//读取输入流中的属性列表
prop.load(in);
//关闭资源
in.close();
//通过键取值,可以得到类的限定名
String className = prop.getProperty("className");
//创建此 Class 对象所表示的类的一个新实例。
Collection coll = (Collection)Class.forName(className).newInstance();
coll.add("123");
coll.add("abc");
coll.add("456");
coll.add("qwe");
System.out.println(coll);
}
}