java f反射_java反射机制

本文深入讲解Java反射机制的基础概念及应用场景,包括如何通过不同方式获取Class对象,如何使用反射调用构造方法、成员变量和成员方法等。同时,还介绍了如何通过反射运行配置文件内容以及如何越过泛型检查。
摘要由CSDN通过智能技术生成

反射定义

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

使用反射

1.获取Class对象

Student类

package com.huchengyue.beans;

public class Student{

private String name;

private int age;

private boolean sex;

public Student(String name, int age, boolean sex){

this.name = name;

this.age = age;

this.sex = sex;

}

public String getName(){

return name;

}

public void setName(String name){

this.name = name;

}

public int getAge(){

return age;

}

public void setAge(int age){

this.age = age;

}

public boolean isSex(){

return sex;

}

public void setSex(boolean sex){

this.sex = sex;

}

@Override

public String toString(){

return "Student{" +

"name='" + name + '\'' +

", age=" + age +

", sex=" + sex +

'}';

}

}

main方法

package com.huchengyue;

import com.huchengyue.beans.Student;

public class Fanshe{

public static void main(String[] args){

//第一种方式获取Class对象

Student stu1 = new Student("sfencs",21,true);//这一new 产生一个Student对象,一个Class对象。

Class stuClass = stu1.getClass();//获取Class对象

System.out.println(stuClass.getName());

//第二种方式获取Class对象

Class stuClass2 = Student.class;

System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个

//第三种方式获取Class对象

try {

Class stuClass3 = Class.forName("com.huchengyue.beans.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名

System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

}

2.获取构造方法并使用

Teacher类

package com.huchengyue.beans;

public class Teacher{

//—————构造方法——————-

//(默认的构造方法)

Teacher(String str){

System.out.println("(默认)的构造方法 s = " + str);

}

//无参构造方法

public Teacher(){

System.out.println("调用了公有、无参构造方法执行了");

}

//有一个参数的构造方法

public Teacher(char name){

System.out.println("姓名:" + name);

}

//有多个参数的构造方法

public Teacher(String name ,int age){

System.out.println("姓名:"+name+"年龄:"+ age);

}

//受保护的构造方法

protected Teacher(boolean n){

System.out.println("受保护的构造方法 n = " + n);

}

//私有构造方法

private Teacher(int age){

System.out.println("私有的构造方法 年龄:"+ age);

}

}

main方法

package com.huchengyue;

import java.lang.reflect.Constructor;

/*

* 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;

*

* 1.获取构造方法:

* 1).批量的方法:

* public Constructor[] getConstructors():所有"公有的"构造方法

public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)

* 2).获取单个的方法,并调用:

* public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:

* public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

*

* 调用构造方法:

* Constructor-->newInstance(Object... initargs)

*/

public class Constructors{

public static void main(String[] args) throws Exception{

//1.加载Class对象

Class clazz = Class.forName("com.huchengyue.beans.Teacher");

//2.获取所有公有构造方法

System.out.println("**********************所有公有构造方法*********************************");

Constructor[] conArray = clazz.getConstructors();

for(Constructor c : conArray){

System.out.println(c);

}

System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");

conArray = clazz.getDeclaredConstructors();

for(Constructor c : conArray){

System.out.println(c);

}

System.out.println("*****************获取公有、无参的构造方法*******************************");

Constructor con = clazz.getConstructor(null);

//1>、因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型

//2>、返回的是描述这个无参构造函数的类对象。

System.out.println("con = " + con);

//调用构造方法

Object obj = con.newInstance();

// System.out.println("obj = " + obj);

// Student stu = (Student)obj;

System.out.println("******************获取私有构造方法,并调用*******************************");

con = clazz.getDeclaredConstructor(char.class);

System.out.println(con);

//调用构造方法

con.setAccessible(true);//暴力访问(忽略掉访问修饰符)

obj = con.newInstance('男');

System.out.println(obj);

}

}

3.获取成员变量并调用

People类

package com.huchengyue.beans;

public class People{

public People(){

}

//**********字段*************//

public String name;

protected int age;

char sex;

private String phoneNum;

@Override

public String toString(){

return "People{" +

"name='" + name + '\'' +

", age=" + age +

", sex=" + sex +

", phoneNum='" + phoneNum + '\'' +

'}';

}

}

main方法

package com.huchengyue;

import com.huchengyue.beans.People;

import java.lang.reflect.Field;

/*

* 获取成员变量并调用:

*

* 1.批量的

* 1).Field[] getFields():获取所有的"公有字段"

* 2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;

* 2.获取单个的:

* 1).public Field getField(String fieldName):获取某个"公有的"字段;

* 2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)

*

* 设置字段的值:

* Field --> public void set(Object obj,Object value):

* 参数说明:

* 1.obj:要设置的字段所在的对象;

* 2.value:要为字段设置的值;

*

*/

public class Fields{

public static void main(String[] args) throws Exception{

//1.获取Class对象

Class stuClass = Class.forName("com.huchengyue.beans.People");

//2.获取字段

System.out.println("************获取所有公有的字段********************");

Field[] fieldArray = stuClass.getFields();

for(Field f : fieldArray){

System.out.println(f);

}

System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");

fieldArray = stuClass.getDeclaredFields();

for(Field f : fieldArray){

System.out.println(f);

}

System.out.println("*************获取公有字段**并调用***********************************");

Field f = stuClass.getField("name");

System.out.println(f);

//获取一个对象

Object obj = stuClass.getConstructor().newInstance();//产生Student对象--》Student stu = new Student();

//为字段设置值

f.set(obj, "刘德华");//为Student对象中的name属性赋值--》stu.name = "刘德华"

//验证

People peo = (People)obj;

System.out.println("验证姓名:" + peo.name);

System.out.println("**************获取私有字段****并调用********************************");

f = stuClass.getDeclaredField("phoneNum");

System.out.println(f);

f.setAccessible(true);//暴力反射,解除私有限定

f.set(obj, "18888889999");

System.out.println("验证电话:" + peo);

}

}

4,获取成员方法并调用

student2类

package com.huchengyue.beans;

public class Student2{

public void show1(String s){

System.out.println("调用了:公有的,String参数的show1(): s = " + s);

}

protected void show2(){

System.out.println("调用了:受保护的,无参的show2()");

}

void show3(){

System.out.println("调用了:默认的,无参的show3()");

}

private String show4(int age){

System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);

return "abcd";

}

}

main方法

package com.huchengyue;

import java.lang.reflect.Method;

/*

* 获取成员方法并调用:

*

* 1.批量的:

* public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)

* public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)

* 2.获取单个的:

* public Method getMethod(String name,Class>... parameterTypes):

* 参数:

* name : 方法名;

* Class ... : 形参的Class类型对象

* public Method getDeclaredMethod(String name,Class>... parameterTypes)

*

* 调用方法:

* Method --> public Object invoke(Object obj,Object... args):

* 参数说明:

* obj : 要调用方法的对象;

* args:调用方式时所传递的实参;

):

*/

public class MethodClass{

public static void main(String[] args) throws Exception{

//1.获取Class对象

Class stuClass = Class.forName("com.huchengyue.beans.Student2");

//2.获取所有公有方法

System.out.println("***************获取所有的”公有“方法*******************");

stuClass.getMethods();

Method[] methodArray = stuClass.getMethods();

for(Method m : methodArray){

System.out.println(m);

}

System.out.println("***************获取所有的方法,包括私有的*******************");

methodArray = stuClass.getDeclaredMethods();

for(Method m : methodArray){

System.out.println(m);

}

System.out.println("***************获取公有的show1()方法*******************");

Method m = stuClass.getMethod("show1", String.class);

System.out.println(m);

//实例化一个Student对象

Object obj = stuClass.getConstructor().newInstance();

m.invoke(obj, "刘德华");

System.out.println("***************获取私有的show4()方法******************");

m = stuClass.getDeclaredMethod("show4", int.class);

System.out.println(m);

m.setAccessible(true);//解除私有限定

Object result = m.invoke(obj, 20);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参

System.out.println("返回值:" + result);

}

}

5.通过反射运行配置文件内容

Student3类

package com.huchengyue.beans;

public class Student3{

public void show(){

System.out.println("is show()");

}

}

main方法

package com.huchengyue;

import java.io.FileReader;

import java.io.IOException;

import java.lang.reflect.Method;

import java.util.Properties;

/*

* 我们利用反射和配置文件,可以使:应用程序更新时,对源码无需进行任何修改

* 我们只需要将新类发送给客户端,并修改配置文件即可

*/

public class Demo{

public static void main(String[] args) throws Exception{

//通过反射获取Class对象

Class stuClass = Class.forName(getValue("className"));//"cn.fanshe.Student"

//2获取show()方法

Method m = stuClass.getMethod(getValue("methodName"));//show

//3.调用show()方法

m.invoke(stuClass.getConstructor().newInstance());

}

//此方法接收一个key,在配置文件中获取相应的value

public static String getValue(String key) throws IOException{

Properties pro = new Properties();//获取配置文件的对象

FileReader in = new FileReader("pro.txt");//获取输入流

pro.load(in);//将流加载到配置文件对象中

in.close();

return pro.getProperty(key);//返回根据key获取的value值

}

}

pro.txt

className = com.huchengyue.Student3

methodName = show

6.通过反射越过泛型检查

import java.lang.reflect.Method;

import java.util.ArrayList;

/*

* 通过反射越过泛型检查

*

* 例如:有一个String泛型的集合,怎样能向这个集合中添加一个Integer类型的值?

*/

public class Demo{

public static void main(String[] args) throws Exception{

ArrayList strList = new ArrayList<>();

strList.add("aaa");

strList.add("bbb");

// strList.add(100);

//获取ArrayList的Class对象,反向的调用add()方法,添加数据

Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象

//获取add()方法

Method m = listClass.getMethod("add", Object.class);

//调用add()方法

m.invoke(strList, 100);

//遍历集合

for(Object obj : strList){

System.out.println(obj);

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值