我是靠谱客的博主 秀丽毛巾,最近开发中收集的这篇文章主要介绍java反射机制初体验2Constructor类Field类Method类 ,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Constructor

Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。

Constructor 允许在将实参与带有底层构造方法的形参的 newInstance() 匹配时进行扩展转换,但是如果发生收缩转换,则抛出 IllegalArgumentException。

示例代码:

View Code
 1 package reflect;
 2
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.Field;
 5 import java.lang.reflect.Method;
 6 import java.util.Iterator;
 7
 8 public class ReflectTest {
 9
10
/**
11 
* @author alan
12 
* @param args
13 
* @throws Exception
14
*/
15
public static void main(String[] args) throws Exception {
16
/*
17 
* Contructor类解析:类的构造方法没有顺序 Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。
18 
* Constructor 允许在将实参与带有底层构造方法的形参的 newInstance() 匹配时进行扩展转换,
19 
* 但是如果发生收缩转换,则抛出 IllegalArgumentException。
20 
*
21 
* 反射比较占用时间,需要缓存。程序性能下降:查看Class源码
22 
* */
23
System.out.println("Contructor类解析");
24
Constructor constructor=String.class.getConstructor(StringBuffer.class); //getConstructor是可变参数,选择构造方法(含一个字符串参数),运行时执行 
25
String string2=(String) constructor.newInstance(new StringBuffer("string"));//通过参数来选择构造方法创建实例。(与构造方法同样类型的变量) 
26
System.out.println(string2);// 编译时无措:二进制代码 运行时出错:Exception in thread "main"
java.lang.IllegalArgumentException: argument type mismatch
27
28
//String string3=(String) constructor.newInstance("string");//参数不同,运行时出错
29
//System.out.println(string3);
30 
}
31 }

 

Class 的newInstance()方法解析。newInstance ()中调用的newInstance0()方法使用缓存机制来保存默认构造方法的实例。

jdk源码解析:

public T newInstance()

        throws InstantiationException, IllegalAccessException

    {

        if (System.getSecurityManager() != null) {

            checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);

        }

        return newInstance0();

    }

 

private T newInstance0()

        throws InstantiationException, IllegalAccessException

    {

        // NOTE: the following code may not be strictly correct under

        // the current Java memory model.

 

        // Constructor lookup

        if (cachedConstructor == null) {    //缓存为空

            if (this == Class.class) {

                throw new IllegalAccessException(

                    "Can not call newInstance() on the Class for java.lang.Class"

                );

            }

            try {

                Class<?>[] empty = {};

                final Constructor<T> c = getConstructor0(empty, Member.DECLARED);//得到无参的构造方法构造实例对象。

                // Disable accessibility checks on the constructor

                // since we have to do the security check here anyway

                // (the stack depth is wrong for the Constructor's

                // security check to work)

                java.security.AccessController.doPrivileged(

                    new java.security.PrivilegedAction<Void>() {

                        public Void run() {

                                c.setAccessible(true);

                                return null;

                            }

                        });

                cachedConstructor = c;     //将c缓存起来,下次调用newInstance时,直接读取缓存并返回

            } catch (NoSuchMethodException e) {

                throw new InstantiationException(getName());

            }

        }

        Constructor<T> tmpConstructor = cachedConstructor;            //调用缓存内的实例对象创建tmpConstructor

 

 

Field

 

Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。

 

Array 允许在执行 get 或 set 访问操作期间进行扩展转换,但如果将发生收缩转换,则抛出一个 IllegalArgumentException。

示例代码:

View Code
 1 package reflect;
 2
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.Field;
 5 import java.lang.reflect.Method;
 6 import java.util.Iterator;
 7
 8 public class ReflectTest {
 9
10
/**
11 
* @author alan
12 
* @param args
13 
* @throws Exception
14
*/
15
public static void main(String[] args) throws Exception {
16
17
18
/*
19 
* Field类解析 Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
20 
* Array 允许在执行 get 或 set 访问操作期间进行扩展转换,但如果将发生收缩转换,则抛出一个
21 
* IllegalArgumentException。
22
*/
23
System.out.println("Field类解析:");
24
ReflectPoint reflectPoint=new ReflectPoint(1, 2);
25
26
Field fieldX=reflectPoint.getClass().getField("x"); //x!=1对应到类字节码的变量,没有对应类对象身上。
27
System.out.println(fieldX.get(reflectPoint)); //在reflectPoint具体对象中的变量
28
29
Field fieldY=reflectPoint.getClass().getDeclaredField("y"); //y不可见
30
fieldY.setAccessible(true); //暴力反射
31 
System.out.println(fieldY.get(reflectPoint));
32
33
System.out.println("替换成员变量中的字符实验");
34
replaceWord(reflectPoint); //替换成员变量中的字符。
35 
System.out.println(reflectPoint);
36
37
38 
}
39
public static void replaceWord(Object object) throws Exception {
40
Field[] fields = object.getClass().getFields();
41
for (Field field : fields) {
42
if (field.getType() == String.class) { // 只有一份字节码,所以使用“==”比较,而非equals
43
String oldWord = (String) field.get(object);
44
String newWord = oldWord.replace("w", "W");
45 
field.set(object, newWord);
46 
}
47 
}
48 
}
49 }
50
51

 辅助ReflectPoint类代码:

View Code
 1 package reflect;
 2
 3 public class ReflectPoint {
 4
public int x;
 5
private
int y;
 6
public String string="helloworld";
 7
 8
public ReflectPoint(int x, int y) {
 9
super();
10
this.x = x;
11
this.y = y;
12 
}
13
14
public String
toString () {
15
return "helloworld has changed to "+string;
16 
}
17 }

 

Method

 

Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。

Method 允许在匹配要调用的实参与底层方法的形参时进行扩展转换;但如果要进行收缩转换,则会抛出 IllegalArgumentException。

1、  得到类中的某个方法,如下示:

Method chatAt=Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);

2、  调用方法,如下示:

通用方式:System.out.println(string.charAt(1));

反射方式:System.out.println(charAt.invoke(string,1));如果传递给Method对象的invoke()方法的一个参数为null时,说明Method对象对应的是一个静态方法。

示例代码:

View Code
 1 package reflect;
 2
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.Field;
 5 import java.lang.reflect.Method;
 6 import java.util.Iterator;
 7
 8 public class ReflectTest {
 9
10
/**
11 
* @author alan
12 
* @param args
13 
* @throws Exception
14
*/
15
public static void main(String[] args) throws Exception {
16
/*
17 
* Method类解析
18
*/
19
System.out.println("Method类解析:");
20
String string = "string";
21
System.out.println("通用方式:"+string.charAt(1));
22
Class class1 = string.getClass();
23
Method charAtMethod = String.class.getMethod("charAt", int.class);
24
System.out.println("反射方式:"+charAtMethod.invoke(string, 1));// 指定对象string调用由此 Method对象charAtMethod表示的底层方法charAt().

25 
}
26 }

 

3、写一个程序,程序能够根据用户提供的类名,去执行该类中的main方法。

示例代码:

View Code
 1 package reflect;
 2
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.Field;
 5 import java.lang.reflect.Method;
 6 import java.util.Iterator;
 7
 8 public class ReflectTest {
 9
10
/**
11 
* @author alan
12 
* @param args
13 
* @throws Exception
14
*/
15
public static void main(String[] args) throws Exception {
16
17
//写一个程序,程序能够根据用户提供的类名,去执行该类中的main方法
18
System.out.println("写一个程序,程序能够根据用户提供的类名,去执行该类中的main方法:");
19
TestArgument.main(new String[]{"1","2","3"});
//普通方式:类的静态方法调用
20
//使用反射方式调用。源程序无法知道类的名称,
21
String startString=args[0];
22
Method mainMethod=Class.forName(startString).getMethod("main", String[].class);
23
//mainMethod.invoke(null, new String[]{"1","2","3"});
//出现错误Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
24
mainMethod.invoke(null, new Object[]{ new String[]{"1","2","3"}});
//invoke第一个参数为null表示为静态方法调用。
25
//mainMethod.invoke(null, (Object)new String[]{"1","2","3"});

26 
}
27 }
28
29 class TestArgument{
30
public static void
main(String[] args) {
31
for (String string : args) {
32 
System.out.println(string);
33 
}
34
35 
}
36
37 }

问题:Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments

原因:jdk1.4语法中,数组中每个元素对应一个参数。为了兼容jdk1.4,javac会按jdk1.4语法处理。即把数组打散成为若干个单独的参数。

 解决方法:

              1、mainMethod.invoke(null, new Object[]{ new String[]{"1","2","3"}});      //再包装一层,拆后为实际所需的参数。此方法效率较低。

              2、mainMethod.invoke(null, (Object)new String[]{"1","2","3"}); //给的是对象,不是数组,不会拆。编译器会做特殊处理,编译时不把参数当作数组对待,也就不会将数组打散为若干个参数了。

转载于:https://www.cnblogs.com/M-Star/archive/2013/02/08/2909455.html

最后

以上就是秀丽毛巾为你收集整理的java反射机制初体验2Constructor类Field类Method类 的全部内容,希望文章能够帮你解决java反射机制初体验2Constructor类Field类Method类 所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(78)

评论列表共有 0 条评论

立即
投稿
返回
顶部