前言:原本是准备一周已更新呢,结果上级要的急,无奈今天继续更新
那什么是反射呢?
官方解释:程序运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
这个介绍已经很通俗了,我就不过多解释。
2.
反射作用?这个简单的说,就是在编译时不需要知道任何事情,对类及类的属性和方法进行操作
3.
我们先看看如何通过反射查看类的信息
- 先获取这个类的对象(三种方式获取方式)
//通过forName方法获取Class对象
Class<?> clazz = Class.forName("com.aaa.Person");
System.out.println(clazz);
//通过class属性获取Class对象
Class<?> clazz2 = Person.class;
System.out.println(clazz2);
//通过某个对象的getClass方法获取对应的Class对象
Person p = new Person();
Class<?> clazz3 = p.getClass();
System.out.println(clazz3);
- 从类中获取信息,类中包含(属性,方法,构造器)
Constructor getConstructor(Class…parameterTypes):返回Class对象对应类的指定参数的public构
造器。
Constructor[] getConstructors():返回Class对象对应类的所有public构造器。e
Constructor getDeclaredConstructor(Class…parameterTypes):返回Class对象对应类的指定参数的
构造器,与构造器访问级别无关。
Constructor[] getDeclaredConstructors():返回Class对象对应类的所有构造器,与构造器访问级别无
关。
//对构造器的操作
public class Reflex_4_1_Person {
private String name;
private int age;
public Reflex_4_1_Person(String name) {
System.out.println("有参构找函数");
}
public Reflex_4_1_Person(String name, int age) {
System.out.println("有参构找函数1");
}
public Reflex_4_1_Person() {
// TODO Auto-generated constructor stub
System.out.println("无参构找函数");
}
public static void main(String[] args) throws Exception{
//获取对象
Class<Reflex_4_1_Person> class1=Reflex_4_1_Person.class;
//获取person类的参数类型String的public构造器
Constructor<Reflex_4_1_Person> con=class1.getConstructor(String.class);
System.out.println("person类的参数类型String的public构造器:\n"+con);
//获取person的所有构造器
Constructor[] con1=class1.getConstructors();
System.out.println("以下person的所有构造器:");
for (Constructor constructor : con1) {
System.out.println(con);
}
Constructor[] con2=class1.getDeclaredConstructors();
System.out.println("以下person的所有构造器:");
for (Constructor constructor : con2) {
System.out.println(con);
}
}
}
//访问Class对应类所包含的方法(Method)
//Method getMethod(String name, Class... parameterTypes) :返回Class对应类的指定public方法。
//Method[] getMethods() :返回Class对应类的所有public方法。
//Method getDeclaredMethod(String name, Class... parameterTypes) :返回Class对应类的指定方
//法,与访问级别无关。
//Method[] getDeclaredMethods() :返回Class对应类的所有方法,与访问级别无关。
public static void main(String[] args) throws Exception{
//获取类对象
Class clazz=Reflex_4_2_2.class;
//获取所有方法
Method[] method=clazz.getDeclaredMethods();
//输出所有方法
System.out.println("Reflex_4_2_2中所有方法");
for (Method m : method) {
System.out.println(m);
}
//输出Reflex_4_2_2中info方法
System.out.println("输出Reflex_4_2_2中info方法");
Method method1=clazz.getMethod("info",String.class);
System.out.println(method1);
}
//访问Class对应类所包含的字段:
//Filed getField(String name) :返回Class对应类的指定public属性。
//Filed[] getFields() :返回Class对应类的所有public属性。
//Field getDeclaredField(String name) :返回Class对应类的指定属性,与访问级别无关。
//Field[] getDeclaredField s() :返回Class对应类的所有属性,与访问级别无关。
public static void main(String[] args) throws Exception, Exception {
Class clazz=Reflex_4_2_3.class;//获取public类对象
Field [] field=clazz.getDeclaredFields();//获取public中所有的属性
System.out.println("public中所有属性如下:");
for (Field field1 : field) {
System.out.println(field1);
}
Field field2=clazz.getField("name");//获取public中public name的属性
System.out.println("public中name属性:"+field2);
}
//访问Class对应类所包含的注解(Annotation)
//<A extends Annotation> A getAnnotation(Class<A> annotationClass):试图获取该Class对应类指定类型的注解,如果该类型的注解不存在则返回null。
//Annotation [] getAnnotations():返回此元素上存在的所有注解。
//Annotation [] getDeclaredAnnotations():返回直接存在于此元素上的所有注解。
public void test1(){
Class clazz = HelloWorldController.class;
//获取Class对应类所有运行时注解
Annotation[] annos = clazz.getAnnotations();
System.out.println("HelloWorldController类上存在的注解有:");
for(Annotation a : annos){
System.out.println(a);
}
//获取Class对应类指定类型的注解
Annotation a = clazz.getAnnotation(HelloWorldController.class);
System.out.println("HelloWorldController类Property类型的注解是:\n"+a);
}
//访问Class对应类所包含的其他成员
//Class[] getDeclaredClasses():返回Class对应类的全部内部类。
//Class[] getClasses():返回Class对应类的全部public内部类。
//Class<?> getDeclaringClass():返回Class对应类的外部类。
//Class[] getInterfaces():返回Class对应类所实现的全部接口。
//int getModifiers():返回Class对应类或接口的所有修饰符。修饰符由public、protected、
//private、final、static、abstract等对应的常量组成,返回的整数应使用Modifier工具类的方法来解码,才可以获得真实的修饰符。
//Package getPackage():获取此类的包。
//String getName():返回Class对应类的名称。
//String getSimpleName():返回Class对应类的简称。
//Class<? super T> getSuperClass():返回Class对应类的父类的对应Class对象。
public class Person implements Animal{
public class Inner1{ }
public class Inner2{ }
public static void main(String[] args) throws Exception {
Class clazz = Person.class;
//获取Class对应类的public内部类
Class[] innerClasses = clazz.getClasses();
System.out.println("Person的public内部类有:");
for(Class c : innerClasses){
System.out.println(c);
}
//获取内部类Inner1对应的Class对象
Class inclazz = Class.forName("com.aaa.Person$Inner1");
//获取Inner1的外部类
Class outClazz = inclazz.getDeclaringClass();
System.out.println("Inner1的外部类是:\n"+outClazz);
//获取Person类实现的接口
Class[] inter = clazz.getInterfaces();
System.out.println("Person类实现的接口有:");
for(Class c : inter){
System.out.println(c);
}
//获取Person类的修饰符常量
int c = clazz.getModifiers();
System.out.println("Person类的修饰符常量是:\n"+c);
//获取Person所在包
Package pn = clazz.getPackage();
System.out.println("Person所在包是:\n"+pn);
//获取Class对应类的类名
String name = clazz.getName();
System.out.println("Class对应类的类名:\n"+name);
//获取Class对应类的类名简称
String sname = clazz.getSimpleName();
System.out.println("Class对应类的类名简称是:\n"+sname);
}
}
上面是通过反射对类的所有基本操作,代码很多,含有很多属性的使用。
用反射生成对象,并操作对象
- 创建对象
public class ObjectPoolFactory {
//定义一个对象池,前面是对象名,后面是实际对象
private Map<String,Object> objectPool = new HashMap<String,Object>();
//定义一个创建对象的方法,该方法只要传入一个字符串类名,程序可以根据该类名生成Java对象
private Object createObject(String className) throws Exception{
//根据字符串来获取对应的Class对象
Class<?> clazz = Class.forName(className);
//使用clazz对应类的默认构造器创建实例
return clazz.newInstance();
}
public void initPool(String fileName){
FileInputStream fis = null;
try{
fis = new FileInputStream(fileName);
Properties props = new Properties();
//从输入流中读取属性列表
props.load(fis);
for(String name:props.stringPropertyNames()){
//创建对象并添加到对象池中
objectPool.put(name, createObject(props.getProperty(name)));
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(fis!=null){
fis.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
public Object getObject(String name){
//从对象池中取出指定name对应的对象
return objectPool.get(name);
}
public static void main(String[] args) {
ObjectPoolFactory pool = new ObjectPoolFactory();
pool.initPool("obj.txt");
System.out.println(pool.getObject("a"));
}
}
- 调用对象
- 当获得某个类的Class对象后,就可以通过Class对象的getMethods方法或者getMethod方法来获取全部方
法(Method对象数组)或指定方法(Method对象)。获得Method对象后,程序就可以通过Method对象的
invoke()方法调用目标对象的方法。
3.访问属性值
getXxx(Object obj):获取obj对象的属性值。此处Xxx对应8个基本类型,如果是 引用类型则取消get后
面的Xxx。
setXxx(Object obj , Xxx val):将obj对象的属性值设置成val。此处Xxx表示8个基本类型,如果是引用类
型则取消set后面的Xxx。
代理我在这就不具体介绍,在下面第四章 模式 章中一起介绍。
**
有的章节会有代码附加!
**