为了账号安全,请及时绑定邮箱和手机立即绑定

java中的反射应用

标签:
Java

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。


反射

我们先创建一个Student类出来。注意类中的成员变量、构造方法、成员方法公共还是私有


package com.reflect;


public class Student {

//成员变量

public String name;//公共

private int age;//私有

//构造方法

public Student() {

super();

// TODO Auto-generated constructor stub

}


//私有构造方法

private Student(String name) {

this.name = name;

}

public Student(String name, int age) {

super();

this.name = name;

this.age = age;

}


//成员方法(getXxx/setXxx)

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 void study() {

System.out.println("我爱学习java!");

}

// 私有

private void study(String string) {

System.out.println("我还爱学习"+string);

}

@Override

public String toString() {

return "Student [name=" + name + ", age=" + age + "]";

}

}



1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

反射概述

反射:反射是通过class文件对象,去使用文件对象的成员方法、构造方法、成员变量

回想之前我们使用对象方法时必须通过new对象去使用。new Student().study(),此时我们就发现了一个问题,小例中我们肯定是知道Student类中是有study()方法的,如果我们想使用用这个类但却不清楚类中的信息,此时反射就起到了一定作用。

其实反射的作用,不止这一点点。如下

反射可以提高程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提高硬编码目标类

Java反射技术应用领域很广,后期如软件测试、JavaBean等都有很重要的作用

许多流行的开源框架例如Struts、Hibernate、Spring在实现过程中都采用了该技术

性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此Java反射机制只要应用在对;灵活性和扩展性要求很高的系统框架上,普通程序不建议使用使用反射会模糊程序内部逻辑:程序员希望在代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。

反射获取Class类对象

要想使用反射,我们必须得到class文件对象,也就是我们要使用的类Class对象

三种获得class文件对象的方法:

Object类的getClass()方法

数据类型的静态属性class

Class类中的静态方法public static Class forName(String classname)

一般我们使用第三种

package com.reflect;


public class Demo {

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

// 方式1

Student p = new Student();

Class c = p.getClass();


Student p2 = new Student();

Class c2 = p2.getClass();


System.out.println(p == p2);// false不是同一Student对象

System.out.println(c == c2);// true是同一class对象


// 方式2

Class c3 = Student.class;

System.out.println(c == c3);//true是同一class对象


// 方式3

// ClassNotFoundException(类找不到时)

Class c4 = Class.forName("com.reflect.Student");

System.out.println(c == c4);//true是同一class对象

}


}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

Class类中相关的几个类


和成员变量有关 Field

和构造方法有关 Constructor

和成员方法有关 Method

有关的几个方法

public T newInstance(Object… initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

反射获取构造方法

先来认识几个方法


public Constructor getConstructor()// 公共构造方法对象

public Constructor[] getConstructors()//所有公共构造方法对象

public Constructor[] getDeclaredConstructors()//所有构造方法对象

public Constructor getDeclaredConstructor()//获取私有构造方法对象

public Constructor<T> getConstructor(Class<?>... parameterTypes)// 参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象

public void setAccessible(boolean flag)// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。  暴力访问

1

2

3

4

5

6

package com.reflect;


import java.lang.reflect.Constructor;


public class ConstructorDemo {

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

// 获取字节码文件对象

Class c = Class.forName("com.reflect.Student");

// 获取所有构造方法

Constructor[] cons = c.getDeclaredConstructors();

for (Constructor con : cons) {

System.out.println(con);

}


// 获取单个构造方法

Constructor con = c.getConstructor();// 返回的是构造方法对象

Constructor con1 = c.getConstructor(String.class, int.class);// 返回的是有参构造方法对象

Constructor con2 = c.getDeclaredConstructor(String.class);

//创建对象 

Object obj = con.newInstance();

Object obj1=con1.newInstance("小米",12);

// 暴力访问

con2.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。

Object obj2 = con2.newInstance("小白");

System.out.println(obj.toString());

System.out.println(obj1.toString());

System.out.println(obj2.toString());

}

}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

运行结果:



反射获取成员变量

**类比上面Constructor类中的方法,这个类也有同样的方法,获取所有成员变量(返回数组),获取私有成员变量等 这里不再赘述 **


package com.reflect;


import java.lang.reflect.Constructor;

import java.lang.reflect.Field;


/*

 * 通过发生获取成员变量并使用

 */

public class FieldDemo {

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

// 获取字节码文件对象

Class c = Class.forName("com.reflect.Student");


// 获取所有的成员变量

Field[] fields = c.getFields();

Field[] fields1 = c.getDeclaredFields();

for (Field field : fields1) {

System.out.println(field);

}


/*

* Person p = new Person(); p.address = "北京"; System.out.println(p);

*/


// 通过无参构造方法创建对象

Constructor con = c.getConstructor();

Object obj = con.newInstance();

System.out.println(obj);


// 获取单个的成员变量

//通过成员变量名

Field nameField = c.getField("name");

// public void set(Object obj,Object value)

// 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

nameField.set(obj, "小红"); // 给obj对象的addressField字段设置值为"北京"

System.out.println(obj);


// 获取age并对其赋值

// NoSuchFieldException  私有变量

Field ageField = c.getDeclaredField("age");

// IllegalAccessException 暴力访问

ageField.setAccessible(true);

ageField.set(obj, 18);

System.out.println(obj);


}

}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

运行结果:



反射获取成员方法

**类比上面Constructor类中的方法,这个类也有同样的方法,获取所有成员方法(返回数组),获取私有成员方法等 这里不再赘述 **


package com.reflect;


import java.lang.reflect.Constructor;

import java.lang.reflect.Method;


public class MethodDemo {

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

// 获取字节码文件对象

Class c = Class.forName("com.reflect.Student");


// 获取所有的方法

Method[] methods = c.getMethods(); // 获取自己的包括继承父亲的公共方法

Method[] methods1 = c.getDeclaredMethods(); // 获取自己的所有的方法

for (Method method : methods1) {

System.out.println(method);

}


Constructor con = c.getConstructor();

Object obj = con.newInstance();

// 获取单个方法并使用

// public void show()

// public Method getMethod(String name,Class<?>... parameterTypes)

// 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型

Method m1 = c.getMethod("study");

// public Object invoke(Object obj,Object... args)

// 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数

m1.invoke(obj); // 调用obj对象的m1方法


System.out.println("----------");

Method m2 = c.getDeclaredMethod("study", String.class);

// NoSuchMethodException 访问私有方法  暴力访问

m2.setAccessible(true);

m2.invoke(obj, "数学");

}

}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

运行结果:https://img1.sycdn.imooc.com//5d8c11d00001ce7d06940316.jpg

————————————————

版权声明:本文为CSDN博主「NULL_YM」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。



点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消