Java反射机制的基本概念与使用_反射基本概念和应用

反射的基本概念什么是反射:反射就是把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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值