反射
是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法;对于任意一个对象,都只能都调用它的任意一个
方法和属性,这种动态获取的信息一级动态调用对象的方法的功能呢个称为java 的反射机制。
反射其实就是动态加载一个指定的类,并获取该类中的所有的内容。而且将字节码文件封装成对象,
并将字节码文件中的内容都封装成对象,这样便于操作这些成员。就是把JAVA类中的各种成分反射成为相应的JAVA类
简单说:反射技术可以对一个类进行解剖。
如果想要对指定名称的字节码文件进行加载
反射的好处:大大的增强了程序的扩展性。
反射的基本步骤:
1、获得Class对象,就是获取到指定的名称的字节码文件对象。
2、实例化对象,获得类的属性、方法或构造函数。
3、访问属性、调用方法、调用构造函数创建对象。
得到类的字节码文件相同,这三种方式。
1.Class cls1=类名.class 相对简单,还是需要明确类名
2.cls1.getclass();必须要明确具体的类,并创建对象
可变参数的使用:
getConstructor方法使用;
获取公共成员变量并使用
获取私有成员变量并使用
获取成员方法并使用
结果:
配置文件:
结果:
方法和属性,这种动态获取的信息一级动态调用对象的方法的功能呢个称为java 的反射机制。
反射其实就是动态加载一个指定的类,并获取该类中的所有的内容。而且将字节码文件封装成对象,
并将字节码文件中的内容都封装成对象,这样便于操作这些成员。就是把JAVA类中的各种成分反射成为相应的JAVA类
简单说:反射技术可以对一个类进行解剖。
如果想要对指定名称的字节码文件进行加载
反射的好处:大大的增强了程序的扩展性。
反射的基本步骤:
1、获得Class对象,就是获取到指定的名称的字节码文件对象。
2、实例化对象,获得类的属性、方法或构造函数。
3、访问属性、调用方法、调用构造函数创建对象。
得到类的字节码文件相同,这三种方式。
1.Class cls1=类名.class 相对简单,还是需要明确类名
2.cls1.getclass();必须要明确具体的类,并创建对象
3.class.forName("完整的类名(带包名)");
person类
package fanshe;
public class person {
public String name;
private int age;
public person() {
// TODO Auto-generated constructor stub
}
private person(String name){
this.name = name;
}
public person(String name, int age) {
this.name = name;
this.age = age;
}
public void show(){
System.out.println("show");
}
public void function(String s){
System.out.println("function"+s);
}
public String returnValue(String name, int age){
return"hello"+name+"**********"+age;
}
private void hello(){
System.out.println("helloworld");
}
@Override
public String toString() {
return "person [name=" + name + ", age=" + age + "]";
}
}
得到类的字节码文件测试demo;
package fanshe;
/**
* @author Angus
* 反射;通过Class文件对象,去使用构造方法,成员变量,成员方法
*
* 怎么得到Class文件对象?
* A:Object对象的getClass方法
* B:数据类型静态的class属性
* C;类 Class的forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象。
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//方式一
person p = new person();
Class c = p.getClass();
person p2 = new person();
Class c2 = p.getClass();
System.out.println(p == p2); //false
System.out.println(c == c2); //true 字节码文件只能是一个
//方式二
Class c3 = person.class;
System.out.println(c==c3); //true
//方式三
Class c4 = Class.forName("fanshe.person");//路径
System.out.println(c==c4); //true
}
}
反射获取构造方法并使用
package fanshe;
import java.lang.reflect.Constructor;
/**
* @author Angus
* 反射获取构造方法并使用
*
* 构造方法:Constructor
* 成员变量:Field
* 成员方法:Method
*/
public class ReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException {
Class c = Class.forName("fanshe.person");
//public Constructor<?>[] getConstructors()
//返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法sss
Constructor[] constructors = c.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("------------------------------");
//getDeclaredClasses这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口
Constructor[] declaredConstructors = c.getDeclaredConstructors();
for (Constructor constructor : declaredConstructors) {
System.out.println(constructor);
}
}
}
可变参数的使用:
package fanshe;
/**
*
* @author Angus
*
* 可变参数
* 格式:
* 修饰符 返回值类型 方法名(数据类型... 变量)
* {
*
* }
* 注意:变量其实为一个数据
* 如果你的方法需要可变参数的数据最好定义在末尾
*
*/
public class ArgsDemo {
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = 30;
System.out.println(sum1(a,b));
System.out.println(sum2(a,b,c));
//......多个数求和呢?
int d = 40;
System.out.println(sun3(a,b,c,d));
System.out.println(sun4(a,b,c,d));
}
/*
* 两个数就和
*/
private static int sum1(int a, int b) {
return a+b;
}
private static int sum2(int a, int b, int c) {
// TODO Auto-generated method stub
return a+b+c;
}
/**
* 可变参数的使用
* @param x
* @return
*/
private static int sun3(int... x){
int result = 0;
for(int i :x){
result += i;
}
return result;
}
/**
* 第一个参数传递给y 剩下的封装数据给x
* 如果int y写到x后边会报错,应为数据全部封装成数据给力x。。。
* @param y
* @param x
* @return
*/
private static int sun4(int y ,int... x){
int result = 0;
for(int i :x){
result += i;
}
return result;
}
}
getConstructor方法使用;
package fanshe;
import java.lang.reflect.Constructor;
/**
* @author Angus
* 反射获取构造方法并使用
*
* 构造方法:Constructor
* 成员变量:Field
* 成员方法:Method
*/
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
Class c = Class.forName("fanshe.person");
//public Constructor<?>[] getConstructors()
//返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法sss
Constructor[] constructors = c.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("------------------------------");
//getDeclaredClasses这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口
Constructor[] declaredConstructors = c.getDeclaredConstructors();
for (Constructor constructor : declaredConstructors) {
System.out.println(constructor);
}
System.out.println("------------------------------");
//public Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor con = c.getConstructor();
//通过构造对象创建对象
//public T newInstance(Object... initargs)
Object newInstance = con.newInstance();
System.out.println(newInstance); //person [name=null, age=0]
}
}
效果;
获取带参构造并使用
package fanshe;
import java.lang.reflect.Constructor;
/**
* @author Angus
* 获取带参构造并使用
*
*/
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
//获取字节码文件对象
Class c = Class.forName("fanshe.person");
//获取构造器对象
// Class[] calsses = new Class[2];
// calsses[0] = String.class;
// calsses[1] = int.class;
// Constructor con = c.getConstructor(calsses);
//改进
// Constructor com = c.getConstructor(new Class[]{String.class,int.class});
//最终
Constructor con = c.getConstructor(String.class,int.class);
//创建对象
Object newInstance = con.newInstance("Angus",26);
System.out.println(newInstance);
//输出结果:person [name=Angus, age=26]
}
}
获取公共成员变量并使用
package fanshe;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
* @author Angus
* 获取公共成员变量并使用
* getFields 获取公共的成员变量
*/
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
//获取字节码文件对象
Class c = Class.forName("fanshe.person");
//获取公共成员变量对象
// Field[] fields = c.getFields(); //
// for (Field field : fields) {
// System.out.println(field);
// //public java.lang.String fanshe.person.name
// }
// System.out.println("---------------------------------");
// //获取所有的成员比那里
// Field[] declaredFields = c.getDeclaredFields();
// for (Field field : declaredFields) {
// System.out.println(field);
// }
System.out.println("---------------------------------");
Constructor con = c.getConstructor();
Object obj = con.newInstance();
//获取一个成员变量
//public void set(Object obj,Object value)
Field field = c.getField("name"); //只能公共的对象
field.set(obj, "Angus");
System.out.println(obj);
//person [name=Angus, age=0]
}
}
获取私有成员变量并使用
package fanshe;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
* @author Angus
* 获取私有成员变量并使用
* getFields 获取公共的成员变量
*
* public static void setAccessible(AccessibleObject[] array,boolean flag)
* 使用单一安全性检查(为了提高效率)为一组对象设置 accessible 标志的便捷方法。
*/
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
//获取字节码文件对象
Class c = Class.forName("fanshe.person");
//创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
//赋值
Field field = c.getField("name"); //私有的会报错
field.set(obj, "Angus");
Field declaredField = c.getDeclaredField("age");
declaredField.setAccessible(true);//设置私有可访问
declaredField.set(obj, 26);
System.out.println(obj);
//person [name=Angus, age=26]
}
}
获取成员方法并使用
package fanshe;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* @author Angus
* 获取成员方法并使用
* public Object invoke(Object obj, Object... args)
* 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
*/
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
//获取字节码文件对象
Class c = Class.forName("fanshe.person");
//创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
//获取方法
//所有公共方法,包括父亲的
Method[] methods = c.getMethods();
for (Method method : methods) {
// System.out.println(method);
}
//获取本类的所有方法
Method[] declaredMethods = c.getDeclaredMethods();
for (Method method : declaredMethods) {
// System.out.println(method);
}
//无参无返回值
Method method1 = c.getMethod("show", null);
method1.invoke(obj, null);
System.out.println("--------------------------");
//带参数无返回值
Method method2 = c.getMethod("function", String.class);
method2.invoke(obj, "Angus");
System.out.println("--------------------------");
//带多个参数有返回值
Method method3 = c.getMethod("returnValue", String.class,int.class);
Object invoke = method3.invoke(obj, "Angus",26);
System.out.println(invoke);
System.out.println("--------------------------");
//私有方法的调用
Method m4 = c.getDeclaredMethod("hello", null);
m4.setAccessible(true);
m4.invoke(obj, null);
}
}
结果:
反射运行配置文件中的内容
package fanshe;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @author Angus
* 反射运行配置文件中的内容
*/
public class Test {
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
FileReader fr = new FileReader("test.properties");
prop.load(fr);
fr.close();
//获取类名
String className = prop.getProperty("className");
//获取方法名
String methodName = prop.getProperty("methodName");
//获取字节码对象
Class c = Class.forName(className);
Constructor con = c.getConstructor();
Object obj = con.newInstance();
Method m = c.getMethod(methodName, null);
m.invoke(obj, null);
}
}
配置文件:
Student类
这样若果获取别的类的方法属性信息,可以直接修改属性文件了。。。。
反射滤过泛型检测。。。
有一个ArrayList<Integer>对象,在集合中添加一个字符串数据,如何实现。。。。
package fanshe;
import java.lang.reflect.Method;
import java.util.ArrayList;
/**
* @author Angus
* 有一个ArrayList<Integer>对象,在集合中添加一个字符串数据,如何实现。。。。
*/
public class ArrayListTest {
public static void main(String[] args) throws Exception{
ArrayList<Integer> array = new ArrayList<>();
//获取字节码问价你对象
Class c = array.getClass();
Method m = c.getMethod("add", Object.class);
m.invoke(array, "hello");
m.invoke(array, "world");
m.invoke(array, "java");
System.out.println(array);
}
}
结果:
最后附上JDK使用文档API 下载