java fx获取textfield_JAVA基础:关于反射的一些总结

本文探讨了Java中的反射机制,介绍了如何通过Class类获取实例,以及使用Constructor调用构造方法。通过示例代码展示了不同获取Class实例的方法在结果上的等价性,并详细解释了Constructor的用法,包括无参和有参构造方法的调用。同时,文章还讨论了如何通过Field访问和修改私有属性,以及如何遍历查找并修改特定类型的属性值。
摘要由CSDN通过智能技术生成

要学反射,先要了解Class这个类,Class是所有Java类的一个总称,Class的实例中存储的是一个类的字节码,获取Class的实例有三种方式:

System.class

new Date().getClass()

Class.forName(“java.lang.String”);

Java不允许使用Class cla = new Class()这种方式获得一个Class的新实例,因为Class的构造方法是私有的,看一段源代码:

1f7c4658ec4509d1047d6a8c724a98e5.png

这段源码里说的很明白,只有JVM才可以创建一个Class对象。

这段源码里说的很明白,只有JVM才可以创建一个Class对象。

那么这三种获取Class实例的方式有什么区别呢?

@Test

public void test1() throws ClassNotFoundException{

String str = "abc";

Class cla1 = str.getClass();

Class cla2 = String.class;

Class cla3 = Class.forName("java.lang.String");

System.out.println(cla1==cla2);

System.out.println(cla2==cla3);

}

输出结果为:

c491ec224cc50475bf923ac1900e4e23.png

根据这结果我们可以推论出,用这三种方式获得的Class实例是一模一样的,但是在实际的开发中我们更多的是使用第三种方式来获得一个Class实例,比如spring框架,我们先在配置文件中写好类名,然后在程序运行的过程中动态加载,获得该类的实例,再执行方法(spring的工作原理基本就这样)。

System.out.println(String.class.isPrimitive());//false

System.out.println(int.class.isPrimitive());//true,判断是否为基本类型

System.out.println(int.class==Integer.class);//false,Integer是类,而int是基本类型

System.out.println(int[].class.isArray());//true

那么反射是什么?

这是别人总结的“反射就是把Java类中的各种成分映射成相应的Java类(比如 属性–>Field、方法–>Method、构造方法–>Contructor、包–>Package)”。

拿到这些相应的Java类之后该怎么用?这是反射学习的重点。

1.Constructor类

1.1 如果想调用一个类的默认无参构造方法,有以下两种方式:

方式一,直接实例化一个Class(这种方式只能调用无参构造方法):

@Test

public void test2(){

try {

Class c = Class.forName("lenve.test.Utils");

c.newInstance();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

输出结果:

2ee56d95b7a7d4664c5efeaacef57a44.png

Utils.java

package lenve.test;

public class Utils {

private String username;

private String password;

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public int add(int a, int b) {

return a + b;

}

public Utils(String str) {

System.out.println(str);

}

public Utils(int a, int b) {

System.out.println(a + b);

}

public Utils() {

System.out.println("this is default constructor!");

}

}

方式二,先获得一个Constructor类,再根据这个类调用无参构造方法。

@Test

public void test3(){

try {

/**

Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数;

Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。

*/

Class c = Class.forName("lenve.test.Utils");

Constructor constructor = c.getConstructor(null);

Utils util = (Utils) constructor.newInstance();

System.out.println(util.add(3, 4));

} catch (ClassNotFoundException e) {

e.printStackTrace();

}catch (NoSuchMethodException e) {

e.printStackTrace();

} catch (SecurityException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

}

输出结果:

84e6676eefd137d2b01426e4e7feeee2.png

1.2 调用一个有参的构造方法

@Test

public void test4(){

try {

Class c = Class.forName("lenve.test.Utils");

//根据参数的类型来确定调用的是哪一个构造方法

Constructor constructor = c.getConstructor(String.class);

//传入该构造方法需要的参数

constructor.newInstance("today is a good day!");

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (NoSuchMethodException e) {

e.printStackTrace();

} catch (SecurityException e) {

e.printStackTrace();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

}

输出结果:

ec6f5b6103dd4bf9558023ca612fe99a.png

2.获得Field并查看相应的实例对象的值,细节都已经在注释中说明:

@Test

public void test5(){

try {

Point p1 = new Point(3, 7);

Field fY = p1.getClass().getField("y");

//fY是字节码中Field对象的一个实例,并不属于某个具体的实例,因此它的值不是7

//这样才是得到p1中y的值

System.out.println(fY.get(p1));

//因为x是私有的,所以不能通过下面的方式获得

// Field fX = p1.getClass().getField("x");

//正确的获得方式应该是这样的

Field fX = p1.getClass().getDeclaredField("x");

//上面的方式拿到x后并不能获得其值,还需要做如下处理

fX.setAccessible(true);

System.out.println(fX.get(p1));

} catch (NoSuchFieldException | SecurityException

| IllegalArgumentException | IllegalAccessException e) {

e.printStackTrace();

}

}

3.获取一个类中的所有String类型的属性,如果该字段的值中有’a’,则全部替换为’b’:

@Test

public void test6(){

Point p = new Point(3, 4);

changeValue(p);

System.out.println(p);

}

private void changeValue(Object obj) {

try {

Field[] fields = obj.getClass().getFields();

for(Field field:fields){

//因为对一个Java类来说,它只有一个字节码,是单例的,所以用==比较就可以了

if(field.getType()==String.class){

String oldStr = (String) field.get(obj);

String newStr = oldStr.replace('a', 'b');

field.set(obj, newStr);

}

}

} catch (SecurityException | IllegalArgumentException

| IllegalAccessException e) {

e.printStackTrace();

}

}

Point.java

public class Point {

private int x;

public int y;

public String username = "zhangsan";

public String password = "lisi";

public Point(int x,int y) {

this.x = x;

this.y = y;

}

@Override

public String toString() {

return "Point [username=" + username +

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值