反射的基本概念什么是反射:反射就是把java中的各个部分,映射成一个个的java对象,也可以理解为这是一种创建对象的方式,然后利用这个对象来做一些事情。既然说反射是反射java类中的各个组成部分,那么一个类的组成部分都有些啥呢,例如一个类中有:成员方法、成员变量、构造方法等信息。利用反射技术咱们可以把这些组成部分映射成一个个对象。
Class ;一个类对象
Constuructor;类中的构造方法
Method;类中的方法
Field;类中的属性
获取class文件的三种方式使用Class类中的静态方法forName(“文件名”)来获取class文件。(假如是java原生态的类,就要写上在那个包里面)
直接用文件名获取
调用Object里面的getclass()方法。 引用.getclass();@java
public class Test01 {
public static void main(String[] args) throws Exception {
//第一种获取class文件的方式
Class c1 = Class.forName("java.util.Date");
//第二种获取class文件的方式。
Class c2 = Date.class;
//第三种获取class文件的方式
Date date = new Date();
Class c3 =date.getClass();
System.out.println(c1==c2);
System.out.println(c2==c3);
}
}
验证获取的是不是同一个class文件,就去判断是否指向同一个内存地址。
运行结果:@java
true
true
Process finished with exit code 0
利用反射创建实例
newInstance();创建此类对象表示类的新实例。就是创建一个无参的构造方法。
如果此类对象没有无参的构造方法,会报java.lang.InstantiationException(类实例化失败)异常。@java
public class ReflectTest01 {
public static void main(String[] args) throws Exception {
//执行了静态块,A这个类加载了,说明这个方法可以将A类扔到java虚拟机里面。
// Class.forName("com.qh.利用反射创建实例.A");
// 不执行静态块
// Class c1= A.class;
//newInstance ;创建一个新的实例
Object o = Class.forName("com.qh.利用反射创建实例.A").newInstance();
if (o instanceof A){
A a = (A)o;
a.m1();
}
}
}
class A{
//静态块,类加载的时候加载,而且只加载一次
static {
System.out.println("Just I miss you !");
}
public void m1(){
System.out.println("张三!");
}
}
利用可变参数创建多个类的实例@java
public class ReflectTest02 {
public static void m1(Class...c) throws Exception{
for (int i = 0; i < c.length; i++) {
Object o = c[i].newInstance();
System.out.println(o);
}
}
public static void main(String[] args) throws Exception {
Class a = Date.class;
Class b= Exception.class;
m1(a,b);
}
}
运行结果@java
Thu Oct 08 15:42:25 CST 2020
java.lang.Exception
Process finished with exit code 0
通过反射机制获取类的属性(Field)Class类Api:
String getSimplename();返回源代码中给出的基础类的简单名称。
int getModifiers()返回此类或接口的Java语言修饰符,以整数编码。
Field getDeclaredField(String name)返回一个 Field对象,它反映此表示的类或接口的指定已声明字段 类对象。
Field [] getDeclaredFields()返回的数组 Field对象反映此表示的类或接口声明的所有字段 类对象。
Field getField(String name)返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段类对象。
Field[] getFields()返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共成员字段类对象。Field类Api:
String getName();返回由此 Field对象表示的字段的名称。
Class> getType()返回一个类对象标识了此表示的字段的声明类型 Field对象。
int getModifiers()返回此类或接口的Java语言修饰符,以整数编码。Modifier类Api:
String toString()返回对象的字符串表示形式。
反编译一个类的所有属性包括修饰符、声明类型@java
public class ReflectTest03 {
public static void main(String[] args) throws Exception {
//1.获取一个类
Class c = Class.forName("java.util.Date");
//2.利用类获取一个属性数组
Field[] fie = c.getDeclaredFields();
StringBuffer sb = new StringBuffer();
sb.append(Modifier.toString(c.getModifiers())+" class
"+c.getSimpleName());
sb.append("{\n");
for (Field field:
fie) {
//3. 获取属性的修饰符
sb.append("\t"+Modifier.toString(field.getModifiers())+"
");
//4.获取属性的类型
sb.append(field.getType().getSimpleName()+" ");
//5.获取属性的名字
sb.append(field.getName()+"\n");
}
sb.append("}");
System.out.println(sb.toString());
}
}
class Person {
private String name ;
public int age;
protected String sex;
boolean hird;
}
运行结果:public class Date{
private static final BaseCalendar gcal
private static BaseCalendar jcal
private transient long fastTime
private transient Date cdate
private static int defaultCenturyStart
private static final long serialVersionUID
private static final String[] wtb
private static final int[] ttb
}
利用反射机制获取类的单个属性:Field类Api:
void set(Object o,Object valut);给对象的属性赋值
Object get(Object o);查看这个对象的属性值Field继承AccessibleObject类Api:
void setAccessible(boolean b);打破属性的封装性。@java
public class ReflectFieldTest01 {
public static void main(String[] args) throws Exception {
Properties p = new Properties();
Reader rea = new FileReader("D:\\Fieldreflect.properties");
p.load(rea);
rea.close();
String fieldName = p.getProperty("FieldName");
//获取一个类
Class c = Class.forName("com.qh.利用反射获得类中的属性.Persion");
Field field = c.getDeclaredField(fieldName);
Object o = c.newInstance();
//打破属性的封装性
field.setAccessible(true);
//给o对象里面的属性赋值。
Scanner input = new Scanner(System.in);
System.out.println("请为该属性赋值:");
field.set(o,input.next());
//输出o对象里面的field属性值
System.out.println("该属性的值:"+field.get(o));
}
}
运行结果:请为该属性赋值:
男
该属性的值:男
利用反射机制获取一个类的方法(Method)
1. 利用反射机制获取一个类的所有方法
Class类Api:
Method[] getDeclaredMethods();返回一个Method类型的数组
Method getDeclaredMethod(String name, 类>... parameterTypes);返回一个 方法对象,它反映此表 示的类或接口的指定声明的方法 类对象。
Method getMethod(String name, 类>... parameterTypes)返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 类对象。
Method getMethods();返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。
Method类Api:
int Modifiers();返回一个方法修饰符所代表的int类型的值
String getname();返回方法的名字
String getReturnType();返回方法的返回值
String getParameterTypes();返回一个方法内的形式参数类型数组@java
public class MethodReflectTest01 {
public static void main(String[] args) throws Exception {
//获取一个类
Class c= Class.forName("com.qh.利用反射获得类中的方法.Register");
//通过一个类获取所有方法
Method[] m = c.getDeclaredMethods();
//将所有的方法遍历
for (Method me:
m) {
//方法的修饰符
int modifiers = me.getModifiers();
System.out.println(Modifier.toString(modifiers));
//方法的返回值
Class returnType = me.getReturnType();
System.out.println(returnType.getSimpleName());
//方法名字
System.out.println(me.getName());
//方法的参数类型
Class[] parameterTypes = me.getParameterTypes();
for (Class parameterType:
parameterTypes) {
System.out.println(parameterType.getSimpleName());
}
}
}
}
运行结果:public
void
love
public
boolean
login
String
String
通过反射机制获取特定的指定方法:
Object invoke(Object o,Object..age);运行o对象的方法,传入age参数,返回一个Object结果。@java
public class MethodReflectTest03 {
public static void main(String[] args) throws Exception {
//获取一个类
Class c= Class.forName("com.qh.利用反射获得类中的方法.Register");
//获取指定的方法,与获取属性不同的是,属性特殊的属性名,而调用单个方法是方法名和形参列表
Method m = c.getDeclaredMethod("login",String.class,String.class);
//运行login方法
Object autonomo = m.invoke(c.newInstance(), "Autonomo", "123");
System.out.println(autonomo);
}
}
里面的方法名,传入的参数都可以写一个properties配置文件来代替,这样写不会吧代码写死,反射就是讲究代码的灵活性。
运行结果:true
运行了login方法
利用反射机制获取一个类的构造方法(Constuructor)
反编译一个类的所有构造方法
所用的方法与Method类里面的一样@java
public class ConstructorReflectTest02 {
public static void main(String[] args) throws Exception {
//获取一个类
Class c = Class.forName("java.lang.String");
//获取这个类里面所有的构造方法,返回一个Constructor类型的数组
Constructor[] co = c.getDeclaredConstructors();
//创建一个StringBuffer进行连续的字符串拼接
StringBuffer sb = new StringBuffer();
sb.append(Modifier.toString(c.getModifiers())+ " class "+c.getSimpleName()+"{\n");
for (Constructor con:
co) {
sb.append("\t");
//获取方法的修饰符
sb.append(Modifier.toString(con.getModifiers())+" ");
//获取方法名,方法名就是类名,可以直接获取类名
sb.append(c.getSimpleName()+"(");
//形参列表类型
Class[] parameterTypes = con.getParameterTypes();
for (int i = 0; i
if (i
sb.append(parameterTypes[i].getSimpleName()+",");
}else{
sb.append(parameterTypes[i].getSimpleName());
}
}
sb.append("){}\n");
}
sb.append("}");
System.out.println(sb.toString());
}
}
这里是输出了String类里面所有的构造方法,只输出了结构,并没有输出具体内容
运行结果:public final class String{
public String(byte[],int,int){}
public String(byte[],Charset){}
public String(byte[],String){}
public String(byte[],int,int,Charset){}
public String(byte[],int,int,String){}
String(char[],boolean){}
public String(StringBuilder){}
public String(StringBuffer){}
public String(byte[]){}
public String(int[],int,int){}
public String(){}
public String(char[]){}
public String(String){}
public String(char[],int,int){}
public String(byte[],int){}
public String(byte[],int,int,int){}
}
获取一个类特有的构造方法
Constructor: Object newInstance(Object...args);使用此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例。
(调用了构造方法就是调用了tostring方法)@java
public class ConstructorReflectTest03 {
public static void main(String[] args) throws Exception {
//获取一个类
Class c = Class.forName("com.qh.利用反射获得类中的构造方法.Person");
//获取指定的构造方法,构造方法名字都一样,只是参数不一样
Constructor con = c.getDeclaredConstructor(String.class,int.class);
//
Object con1 = con.newInstance("张三", 15);
System.out.println(con1);
运行结果Person{name='张三', age=15}
利用反射机制获取类的父接口和父类
Class类:
Class getSuperclass(); 返回 类表示此所表示的实体(类,接口,基本类型或void)的超类 类 。
Class[] getInterfaces();确定由该对象表示的类或接口实现的接口。@java
public class ConstructorReflectTest03 {
public static void main(String[] args) throws Exception {
//获取一个类
Class c = Class.forName("com.qh.利用反射获得类中的构造方法.Person");
//获取指定的构造方法,构造方法名字都一样,只是参数不一样
Constructor con = c.getDeclaredConstructor(String.class,int.class);
//
Object con1 = con.newInstance("张三", 15);
System.out.println(con1);
}
}
运行结果:继承的父类:Object
实现的父接口:
Serializable
Comparable
CharSequence