1.反射机制的概念:
主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息。
反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
类中有什么信息,利用反射机制就能可以获得什么信息,不过前提是得知道类的名字。
2.反射机制的作用
在运行时判断任意一个对象所属的类;
在运行时获取类的对象;
在运行时访问java对象的属性,方法,构造方法等。
(所有类都是class实例)
3.反射机制的优缺点
首先要搞清楚为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念。
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
反射机制的优点:可以实现动态创建对象和编译,体现出很大的灵活性(特别是在J2EE的开发中它的灵活性就表现的十分明显)。通过反射机制我们可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。
比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。
反射机制的缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它 满足我们的要求。这类操作总是慢于只直接执行相同的操作。
反射机制的示例:
所列都是class的实例
package reflect;
/**
* 获得一个对象完整的包名和类名
*/
class Reflect {
//example code
}
class Demo {
public static void main(String[] args) {
//初始化Reflect
Reflect reflect = new Reflect();
//获取Reflect对象的包名和类名
System.out.println(reflect.getClass().getName());
}
}
运行结果:
reflect.Reflect
----------
2.实例化class对象(获取类对象的三种方式)
package reflect;
/**
* 实例化类对象,获取类对象的三种方式
*/
class Reflect {
//example code
}
class Demo {
public static void main(String[] args) {
Class<?> demo1 = null;
Class<?> demo2 = null;
Class<?> demo3 = null;
//第一种方式
String className = "reflect.Reflect";
try {
demo1 = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//第二种方式
demo2 = new Reflect().getClass();
// 第三种方式
demo3 = Reflect.class;
// 打印结果
System.out.println("第一种"+demo1.getName());
System.out.println("第二种"+demo2.getName());
System.out.println("第三种"+demo3.getName());
}
}
运行结果:
第一种reflect.Reflect
第二种reflect.Reflect
第三种reflect.Reflect
注释: 准确的讲是一个ClassLoader下,一种类,只会有一个类对象存在,3种方式
1. Class.forName
2. Hero.class
3. new Hero().getClass()
在一个JVM中,一种类,只会有一个类对象存在。所以以上三种方式取出来的类对象,都是一样的。
3.通过Class实例化其他类的对象
实例化Person对象初始化Person对象,并对Person属性进行操作
注:Class.newInstance只能调用无参构造
Constructor.newINstance只能调用有参构造
测试类代码:
package reflect;
/**
* 通过反射获取Person的属性
*
* @author BxTizen
*/
public class PersonReflect {
public static void main(String[] args) {
// 建立Class模型对象
Class<?> demo = null;
//获取Person类对象,同时会初始化类的属性
try {
demo = Class.forName("reflect.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//准备一个Person类的属性,指向null
Person person = null;
//通过 newInstance实例化对象
try {
person = (Person) demo.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//给实例化对象赋值
person.setAge(23);
person.setName("23333");
//打印person的属性
System.out.println(person);
}
}
----------
Person实体类:
package reflect;
/**
* 通过反射获取Person的属性
*
* @author BxTizen
*/
public class PersonReflect {
public static void main(String[] args) {
// 建立Class模型对象
Class<?> demo = null;
//获取Person类对象,同时会初始化类的属性
try {
demo = Class.forName("reflect.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//准备一个Person类的属性,指向null
Person person = null;
//通过 newInstance实例化对象
try {
person = (Person) demo.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//给实例化对象赋值
person.setAge(23);
person.setName("23333");
//打印person的属性
System.out.println(person);
}
}
运行的结果:
Person{name='23333', age=23}
----------
4.通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)
首先,了解一下构造器
获取类的构造器
首先介绍一下Constructor类,这个类用来封装反射得到的构造器,Class有四个方法来获得Constructor对象
public Constructor<?>[] getConstructors() 返回类中所有的public构造器集合,默认构造器的下标为0
public Constructor<T> getConstructor(Class<?>... parameterTypes) 返回指定public构造器,参数为构造器参数类型集合
public Constructor<?>[] getDeclaredConstructors() 返回类中所有的构造器,包括私有
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回任意指定的构造器
获取类的成员变量
成员变量用Field类进行封装,主要的方法非常的类似:
public Field getDeclaredField(String name) 获取任意指定名字的成员
public Field[] getDeclaredFields() 获取所有的成员变量
public Field getField(String name) 获取任意public成员变量
public Field[] getFields() 获取所有的public成员变量
获取类的方法
public Method[] getMethods() 获取所有的共有方法的集合
public Method getMethod(String name,Class<?>... parameterTypes) 获取指定公有方法 参数1:方法名 参数2:参数类型集合
public Method[] getDeclaredMethods() 获取所有的方法
public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取任意指定方法
(以上的了解一下,可以查询javaAPI文档详细的)
Constructor<?> cons[]=demo.getConstructors();
//无参构造函数
Object object0 = (Object)cons[0].newInstance();
Object object1 = (Object)cons[1].newInstance(parameter);
//多参构造函数
Object object2 = (Object)cons[2].newInstance(parameter1,parameter);
构造函数取出来是有顺序的,Constructor<?> cons[]=cls.getConstructors()的cons[]数组下标对应的对象类里面的构造函数顺序相反,如上例中:最后一个构造方法Person(String name, int age)对应于cons[0],第一个构造方法Person()对应于cons[3];顺序不对会造成参数不正确的异常:
接下来看代码示例:
package reflect;
import java.lang.reflect.Constructor;
public class PersonReflect2 {
public static void main(String[] args) {
Class
实体类:
package reflect;
public class Person {
private int age;
private String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(int age) {
this.age = age;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
运行结果:
Person{age=0, name='null'}
Person{age=0, name='Rollen'}
Person{age=20, name='null'}
Person{age=20, name='Rollen'}
----------
5.返回一个构造类的实接口
接口类:
package reflect1;
public interface China {
public static final String name = “Rollen”;
public static int age = 20;
public void sayChina();
public void sayHello(String name, int age);
}
接口实现实体类:
package reflect1;
public class Person implements China {
private String sex;
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Person() {
}
@Override
public void sayChina() {
System.out.println("hello ,china");
}
@Override
public void sayHello(String name, int age) {
System.out.println(name + " " + age);
}
}
测试类:
package reflect1;
public class Hello {
public static void main(String[] args) {
Class
----------
6.取得其他类中的父类
package reflect1;
public class Hello {
public static void main(String[] args) {
Class
----------
7.获得其他类中的全部构造函数
package reflect1;
import java.lang.reflect.Constructor;
public class Hello {
public static void main(String[] args) {
Class
运行结果:
构造方法: public reflect1.Person()
----------
获取构造方法的全部:
package reflect1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Hello {
public static void main(String[] args) {
Class
运行结果:
构造方法: public reflect1.Person(){}
----------
8.取得其他类的全部属性,将这些整理在一起,也就是通过class取得一个类的全部框架
package reflect1;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Hello {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("reflect1.Person");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("===============本类属性========================");
// 取得本类的全部属性
Field[] field = demo.getDeclaredFields();
for (int i = 0; i < field.length; i++) {
// 权限修饰符
int mo = field[i].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = field[i].getType();
System.out.println(priv + " " + type.getName() + " "
+ field[i].getName() + ";");
}
System.out.println("===============实现的接口或者父类的属性========================");
// 取得实现的接口或者父类的属性
Field[] filed1 = demo.getFields();
for (int j = 0; j < filed1.length; j++) {
// 权限修饰符
int mo = filed1[j].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = filed1[j].getType();
System.out.println(priv + " " + type.getName() + " "
+ filed1[j].getName() + ";");
}
}
}
运行结果:
===============本类属性========================
private java.lang.String sex;
===============实现的接口或者父类的属性========================
public static final java.lang.String name;
public static final int age;
----------
9.通过反射调用其他类中的方法
package reflect1;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Hello {
public static void main(String[] args) {
Class
运行结果:
hello ,china
Rollen 20
----------
10.调用其他类的set和get方法
package reflect1;
import java.lang.reflect.Method;
public class Hello {
public static void main(String[] args) {
Class
运行结果:
男
----------
11.通过反射操作属性
package reflect1;
import java.lang.reflect.Field;
public class Hello {
public static void main(String[] args) throws Exception {
Class
运行结果:
男
----------
12.通过反射取得并修改数组的信息
package reflect1;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
public class Hello {
public static void main(String[] args) {
int[] temp={1,2,3,4,5};
Class
运行结果:
数组类型: int
数组长度 5
数组的第一个元素: 1
修改之后数组第一个元素为: 100
----------
13.修改数组大小通过反射
package reflect1;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
public class Hello {
public static void main(String[] args) {
int[] temp={1,2,3,4,5,6,7,8,9};
int[] newTemp=(int[])arrayInc(temp,15);
print(newTemp);
System.out.println(“=====================”);
String[] atr={“a”,”b”,”c”};
String[] str1=(String[])arrayInc(atr,8);
print(str1);
}
/**
* 修改数组大小
* */
public static Object arrayInc(Object obj,int len){
Class
运行结果:
数组长度为: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =====================
数组长度为: 8
a b c null null null null null
Process finished with exit code 0
----------
14.获取类加载器
实体类
package reflect2;
public class Demo {
//test
}
测试类:
package reflect2;
public class DemoTest {
public static void main(String[] args) {
Demo demo = new Demo();
System.out.println(“类加载器”+demo.getClass().getClassLoader().getClass().getName());
}
}
“`