黑马程序员---Java高新技术(三)--反射
2012-09-26 10:25
405 查看
------- android培训、java培训、期待与您交流! ----------
15、反射的基础Class类
Java应用程序中的类和接口。枚举是一种类,注释是一种接口。
1、什么是Class?
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。(比如:众多的人用Person表示,众多的Java类用Class表示)。
2、Class类的各个实例对象是什么?
1、Person类的实例对象是张菲这样的人,而Class实例对应各个类在内存中的字节码(例如Person类的字节码,String类的字节码)
2、一个类被加载到内存中,占用一定的存储空间,这个空间里面的内容就是类的字节码。不同的类字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,而这个类型是什么呢?(我想应该是字节码)
3、获取字节码的实例对象(三种方式)
1、类名.class;例如:int[].class整型数组的字节码
2、对象.getClass(
);例如:new Integer(7).getClass()获取整型保证类对象的字节码
3、Class.forName(“类名”);例如:Class.forName(“com.mysql.jdbc.Driver”)获取mysql驱动字节码
4、九个预定义Class实例对象
表示八个基本类型和 void。
基本的 Java类型(
cls = void.class,就表示一个对象。Class的对象就是一个字节码。比如:Class a = A.class就是代表A类的一个字节码,而这个字节码的类名就是Class。p1.getClass(
)就表示获取p1对象的字节码。
1、 Class.
isPrimitive():判定指定的
2、 Integer.TYPE
== int.class//true,在Integer中Integer.TYPE表示基本类型
Class实例。
总之,只要在源程序中出现的类型,都有各自的Class实例对象。例如int[],void。
5、面试题:Class.forName( )的作用?
就是返回字节码,返回的方式有两种:1、字节码曾经被加载过,已经呆在虚拟机里,直接返回;2、java虚拟机里还没有这个字节码,则用类记载器去加载,把加载的字节码缓存在虚拟机里面。
反射的精辟理解:就是把Java类中的各种成分映射成相应的java类
示例代码:
package staticImport.cn.itcast.day1;
import java.lang.reflect.Constructor;
publicclass
RefectTest {
publicstaticvoid
main(String args[])throws Exception {
String str =
"abc" ;
Class cls1 = str.getClass();//获取字节码的第一种方式
Class cls2 = Class.forName("java.lang.String");//获取字节码的第二种方式,比较常用
Class cls3 = String.class;//获取字节码的第三种方式
System.out.println(cls1
==cls2);//true
System.out.println(cls1
== cls3);//ture
System.out.println(cls3.isPrimitive());//false,判断是否是原始数据类型
System.out.println(int.class.isPrimitive());//true
//基本数据类型的包装类也不是原始数据类型
System.out.println(Integer.class.isPrimitive());//false
System.out.println(Integer.class
== int.class);//false
//包装类的type返回包装的基本数据类型的Class实例
System.out.println(Integer.TYPE
== int.class);//true
//数组类型的字节码对象也不是基本数据类型
System.out.println(int[].class.isArray());//true
}
}
16、构造方法的反射应用Constructor
1、Constructor类代表某个类中的一个构造方法
2、得到某个类中所有的构造方法
Constructor[ ]constructors = Class.forName(“java.lang.String”).getConstructors();
3、 得到某一个构造方法
Constructor constructor = Class.forName(“java.lang.String”)
.getConstructor(StringBuffer.class );
//获取方法时,要用到参数的类型,当然这个类型也是字节码
4、 创建对象实例
通常方式:String str = new String(new StringBuffer(“abc”));
反射方式:String str = (String)constructor.newInstance(new StringBuffer(“abc”));
//调用获得的方法时,要用到上面相同类型的实例对象
5、 Class.newInstance()方法
例如:String obj =(String)Class.forName(“java.lang.String”).newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例。
方法内部是怎样编写的呢?利用了缓存机制来保存默认构造方法的实例对象
示例代码:
package staticImport.cn.itcast.day1;
import java.lang.reflect.Constructor;
publicclass
RefectTest {
publicstaticvoid
main(String args[])throws Exception {
//new String(new StringBuffer("abc"))用反射的原理来实现
//实现--->拿着字节码--->搞一对象--->用搞出的对象,调用newInstance(),步骤详细解说:
//搞出的某种类型的(比如String类型)构造方法对象,到底对应着这种类型的(比如String类型)哪一个构造方法
//如下三条语句有很多异常。而且getConstructor利用了jdk1.5新特性,可变参数列表
Constructor constructor = Class.forName("java.lang.String")
.getConstructor(StringBuffer.class);
String string = (String)constructor.newInstance(new
StringBuffer("abc"));//【2】
System.out.println(string.charAt(0));
//两个StringBuffer:第一个StringBuffer表示选择哪个构造方法,
//第二个StringBuffer表示,用这个构造方法的时候还得传递一个StringBuffer的对象进去
//为什么要强制类型转换?1、因为程序在编译的时候,查看等号左右两边的类型,左边为String,
//右边函数返回Object所以类型不一致,导致编译失败(1的解释不正确)2、程序在编译的时候,
//严格进行语法检查,没有执行等号右边的东西,不知道constructor是String类型的还是其它类型的,
//所以在执行【2】的时候,constructor对象创建的实例对象是什么类型的人家也不知道,所以要类型转换
//告诉编译器我的返回值类型是String
}
}
17、成员变量反射(Field类)
1、 Filed类代表某个类中的一个成员变量
2、 得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?
答:是对应到类上面的变量。字段fieldX代表的是x的定义,而不是具体的x变量。
3、getField方法只能访问public修饰的成员。如果想访问访问非public成员,就用getDeclaredField方法,并且用setAccessible(true)来修饰。
示例代码:
package staticImport.cn.itcast.day1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
publicclass
RefectTest {
publicstaticvoid
main(String args[])throws Exception {
/**Field类**/
ReflectPoint point =
new ReflectPoint(3,5);
Field fieldY = point.getClass().getField("y");
//只是fieldY的值是多少?5,错!这里的fieldY代表类字节码身上的变量,是类身上的,
//没有对应到对象身上。不代表某一个对象的属性值。如果想要获取某一个对象的属性值,就用get方法
/*老师总结:fieldY不是对象身上的变量,而是类上的,要用它去取某个对象上对应的属性值*/
System.out.println(fieldY);
System.out.println("获取point对象的y属性:"+fieldY.get(point));
/*如果x的属性用private修饰,将抛出则该方法将抛出一个
IllegalAccessException异常
Field fieldX = point.getClass().getField("x");
System.out.println(fieldX.get(point));
如果要想访问:则调用Class中的getDeclaredField()*/
Field fieldX = point.getClass().getDeclaredField("x");
fieldX.setAccessible(true);
System.out.println("获取point对象的x属性:"+fieldX.get(point));
/**问题:将任意一个对象中的所有String类型的成员变量,所对应的字段的内容中的b改为a*/
changeStringValue(point);
System.out.println(point);
}
publicstaticvoid
changeStringValue(Object obj)throws Exception {
//getFields方法可以访问可访问的公共字段,当然protect、private的都不可以访问
Field[] fields = obj.getClass().getFields();
for(Field
field:fields){
System.out.println("1111"+field.get(obj));
if(field.getType()
==String.class){
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('a','b');
field.set(obj, newValue);
}
}
}
}
class ReflectPoint{
privateintx;
publicinty;
public
Stringstr1 ="basketball";
protected
Stringstr2 ="aaaaaaaaaaCCCCCCCC";
public
Stringstr3 ="ababababa";
public
ReflectPoint(int x,
int y) {
super();
this.x
= x;
this.y
= y;
}
public
String toString(){
returnstr1+" "+str2+" "+str3;
}
}
18、成员方法的反射(Method类)
强调一下,Method类的实例对象是类中的方法,而不是对象中的方法
1、 Method类代表某个类中的一个成员方法
2、 得到类中的某个方法
Method charAt = Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);
3、 调用方法
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str,1))
如果传递给Method对象的invoke()方法的第一个参数为null,那就说明Method对象对应的是一个静态方法
4、 jdk1.4与jdk1.5在invoke方法上的区别
JDK1.5:public
Object invoke(Object obj, Object……args)
JDK1.4:public
Object invoke(Object obj,Object[ ]args)
Jdk1.5为了能够兼容jdk1.4,所以jdk1.5也会按照jdk1.4的语法使用invoke方法。需要将一个数组作为参数传递给invoke方法时,数组中每个元素分别对应被调用方法中的一个元素。故,调用charAt方法的代码也可以用jdk1.4改写为charAt.invoke(
“str”,new Object[]{1})
总结:Jdk1.4与Jdk1.5在反射的地方许多方法都不相同,1.4用数组,1.5用可变参数列表
专家模式:谁拥有数据,谁就是干这个事儿的专家,那么这个方法就应该分配给谁。
示例代码:
/**Method类*/RefectTest.java类中
Method charAt = str.getClass().getMethod("charAt",int.class);
System.out.println(charAt.invoke(str,
1));
System.out.println(charAt.invoke(str,new
Object[]{2}));//用jdk1.4的方式进行调用,Object数组长度为1
//invoke:对带有指定参数的指定对象调用由此
Method 对象表示的底层方法。
//如果底层方法是静态的,那么可以忽略指定的obj
参数。该参数可以为 null。因为静态方法时不需要对象的!
System.out.println(str.getClass().getMethod("valueOf",float.class).invoke(null,
12.3f));//12.3
19、对接收数组参数的成员方法进行反射(深入理解Method的调用)
目标:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法?此处不用普通方式调用,而用反射方式调用,为什么?
答:关于那个问号的解释:我的源程序根本就不知道执行那个类,而执行的类是根据参数来决定的,你告诉我执行A类,我就执行A类,你告诉我执行B类,我就执行B类。一句话总结:用反射的方式去调用某一个类的main方法的时候,这个类是未知的,可变的,而不是固定的,在这种情况下用普通的方式调用某个类的主方法是行不通的!
问题:invoke方法中的参数问题?
答:启动Java程序的main方法的参数是一个字符串数组,即public
static void main(String args[]),通过反射采用者个main方法时,如果为invoke方法传递参数呢?按jdk1.5的说法,整个数组时一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底用那种语法惊醒处理呢?jdk1.5要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用main
Method.invoke(null,new String[]{“XXX”},javac只能把它当做jdk1.4的语法进行理解,而不是把它当做jdk1.5的语法进行解释,因此会出现参数类型不对的问题
解决方案:
//第一种:将字符串转换成Object对象。注意每一个的数组父类都是Object。
//就相当于跟编译器说:我是一个Object对象不是一个数组,不要给我拆包了!
mainMethod.invoke(null,
(Object)new String[]{"abc","def","ghi"});
//第二种:将字符串数组作为Object数组中的一个元素
mainMethod.invoke(null,new
Object[]{new String[]{"abc","def","ghi"}});
之所以能这么包装,原因是,所有的数组类型的父类都是Object。
示例代码:
package staticImport.cn.itcast.day1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
publicclass
RefectTest {
publicstaticvoid
main(String args[])throws Exception {
/**Method类*/
Method charAt = str.getClass().getMethod("charAt",int.class);
System.out.println(charAt.invoke(str,
1));
System.out.println(charAt.invoke(str,new
Object[]{2}));//用jdk1.4的方式进行调用,Object数组长度为1
//invoke:对带有指定参数的指定对象调用由此
Method 对象表示的底层方法。
//如果底层方法是静态的,那么可以忽略指定的obj
参数。该参数可以为 null。因为静态方法时不需要对象的!
System.out.println(str.getClass().getMethod("valueOf",float.class).invoke(null,
12.3f));
/**Method的高级应用:
写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法?*/
//常用方式:TestArguments.main(new
String[]{"abc","def","ghi"});
String startingMainClass = args[0];
//参数为将要运行的java类名,main方法的参数为字符串数组
Method mainMethod = Class.forName(startingMainClass).getMethod("main",
String[].class);
//invoke为方法的调用,main方法为static方法,所以第一个参数为null
//第一种:将字符串转换成Object对象。注意每一个的数组父类都是Object。
//就相当于跟编译器说:我是一个Object对象不是一个数组,不要给我拆包了!
mainMethod.invoke(null,
(Object)new String[]{"abc","def","ghi"});
//第二种:将字符串数组作为Object数组中的一个元素
mainMethod.invoke(null,new
Object[]{new String[]{"abc","def","ghi"}});
}
}
class TestArguments{
publicstaticvoid
main(String args[]){
for(String
arg :args){
System.out.println(arg);
}
}
}
------- android培训、java培训、期待与您交流! ----------
15、反射的基础Class类
Class类的实例表示正在运行的
Java应用程序中的类和接口。枚举是一种类,注释是一种接口。
1、什么是Class?
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。(比如:众多的人用Person表示,众多的Java类用Class表示)。
2、Class类的各个实例对象是什么?
1、Person类的实例对象是张菲这样的人,而Class实例对应各个类在内存中的字节码(例如Person类的字节码,String类的字节码)
2、一个类被加载到内存中,占用一定的存储空间,这个空间里面的内容就是类的字节码。不同的类字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,而这个类型是什么呢?(我想应该是字节码)
3、获取字节码的实例对象(三种方式)
1、类名.class;例如:int[].class整型数组的字节码
2、对象.getClass(
);例如:new Integer(7).getClass()获取整型保证类对象的字节码
3、Class.forName(“类名”);例如:Class.forName(“com.mysql.jdbc.Driver”)获取mysql驱动字节码
4、九个预定义Class实例对象
表示八个基本类型和 void。
基本的 Java类型(
boolean、
byte、
char、
short、
int、
long、
float和
double)和关键字
void也可以表示为
Class对象。例如:Class
cls = void.class,就表示一个对象。Class的对象就是一个字节码。比如:Class a = A.class就是代表A类的一个字节码,而这个字节码的类名就是Class。p1.getClass(
)就表示获取p1对象的字节码。
1、 Class.
isPrimitive():判定指定的
Class对象是否表示一个基本类型。
2、 Integer.TYPE
== int.class//true,在Integer中Integer.TYPE表示基本类型
int的
Class实例。
总之,只要在源程序中出现的类型,都有各自的Class实例对象。例如int[],void。
5、面试题:Class.forName( )的作用?
就是返回字节码,返回的方式有两种:1、字节码曾经被加载过,已经呆在虚拟机里,直接返回;2、java虚拟机里还没有这个字节码,则用类记载器去加载,把加载的字节码缓存在虚拟机里面。
反射的精辟理解:就是把Java类中的各种成分映射成相应的java类
示例代码:
package staticImport.cn.itcast.day1;
import java.lang.reflect.Constructor;
publicclass
RefectTest {
publicstaticvoid
main(String args[])throws Exception {
String str =
"abc" ;
Class cls1 = str.getClass();//获取字节码的第一种方式
Class cls2 = Class.forName("java.lang.String");//获取字节码的第二种方式,比较常用
Class cls3 = String.class;//获取字节码的第三种方式
System.out.println(cls1
==cls2);//true
System.out.println(cls1
== cls3);//ture
System.out.println(cls3.isPrimitive());//false,判断是否是原始数据类型
System.out.println(int.class.isPrimitive());//true
//基本数据类型的包装类也不是原始数据类型
System.out.println(Integer.class.isPrimitive());//false
System.out.println(Integer.class
== int.class);//false
//包装类的type返回包装的基本数据类型的Class实例
System.out.println(Integer.TYPE
== int.class);//true
//数组类型的字节码对象也不是基本数据类型
System.out.println(int[].class.isArray());//true
}
}
16、构造方法的反射应用Constructor
1、Constructor类代表某个类中的一个构造方法
2、得到某个类中所有的构造方法
Constructor[ ]constructors = Class.forName(“java.lang.String”).getConstructors();
3、 得到某一个构造方法
Constructor constructor = Class.forName(“java.lang.String”)
.getConstructor(StringBuffer.class );
//获取方法时,要用到参数的类型,当然这个类型也是字节码
4、 创建对象实例
通常方式:String str = new String(new StringBuffer(“abc”));
反射方式:String str = (String)constructor.newInstance(new StringBuffer(“abc”));
//调用获得的方法时,要用到上面相同类型的实例对象
5、 Class.newInstance()方法
例如:String obj =(String)Class.forName(“java.lang.String”).newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例。
方法内部是怎样编写的呢?利用了缓存机制来保存默认构造方法的实例对象
示例代码:
package staticImport.cn.itcast.day1;
import java.lang.reflect.Constructor;
publicclass
RefectTest {
publicstaticvoid
main(String args[])throws Exception {
//new String(new StringBuffer("abc"))用反射的原理来实现
//实现--->拿着字节码--->搞一对象--->用搞出的对象,调用newInstance(),步骤详细解说:
//搞出的某种类型的(比如String类型)构造方法对象,到底对应着这种类型的(比如String类型)哪一个构造方法
//如下三条语句有很多异常。而且getConstructor利用了jdk1.5新特性,可变参数列表
Constructor constructor = Class.forName("java.lang.String")
.getConstructor(StringBuffer.class);
String string = (String)constructor.newInstance(new
StringBuffer("abc"));//【2】
System.out.println(string.charAt(0));
//两个StringBuffer:第一个StringBuffer表示选择哪个构造方法,
//第二个StringBuffer表示,用这个构造方法的时候还得传递一个StringBuffer的对象进去
//为什么要强制类型转换?1、因为程序在编译的时候,查看等号左右两边的类型,左边为String,
//右边函数返回Object所以类型不一致,导致编译失败(1的解释不正确)2、程序在编译的时候,
//严格进行语法检查,没有执行等号右边的东西,不知道constructor是String类型的还是其它类型的,
//所以在执行【2】的时候,constructor对象创建的实例对象是什么类型的人家也不知道,所以要类型转换
//告诉编译器我的返回值类型是String
}
}
17、成员变量反射(Field类)
1、 Filed类代表某个类中的一个成员变量
2、 得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?
答:是对应到类上面的变量。字段fieldX代表的是x的定义,而不是具体的x变量。
3、getField方法只能访问public修饰的成员。如果想访问访问非public成员,就用getDeclaredField方法,并且用setAccessible(true)来修饰。
示例代码:
package staticImport.cn.itcast.day1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
publicclass
RefectTest {
publicstaticvoid
main(String args[])throws Exception {
/**Field类**/
ReflectPoint point =
new ReflectPoint(3,5);
Field fieldY = point.getClass().getField("y");
//只是fieldY的值是多少?5,错!这里的fieldY代表类字节码身上的变量,是类身上的,
//没有对应到对象身上。不代表某一个对象的属性值。如果想要获取某一个对象的属性值,就用get方法
/*老师总结:fieldY不是对象身上的变量,而是类上的,要用它去取某个对象上对应的属性值*/
System.out.println(fieldY);
System.out.println("获取point对象的y属性:"+fieldY.get(point));
/*如果x的属性用private修饰,将抛出则该方法将抛出一个
IllegalAccessException异常
Field fieldX = point.getClass().getField("x");
System.out.println(fieldX.get(point));
如果要想访问:则调用Class中的getDeclaredField()*/
Field fieldX = point.getClass().getDeclaredField("x");
fieldX.setAccessible(true);
System.out.println("获取point对象的x属性:"+fieldX.get(point));
/**问题:将任意一个对象中的所有String类型的成员变量,所对应的字段的内容中的b改为a*/
changeStringValue(point);
System.out.println(point);
}
publicstaticvoid
changeStringValue(Object obj)throws Exception {
//getFields方法可以访问可访问的公共字段,当然protect、private的都不可以访问
Field[] fields = obj.getClass().getFields();
for(Field
field:fields){
System.out.println("1111"+field.get(obj));
if(field.getType()
==String.class){
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('a','b');
field.set(obj, newValue);
}
}
}
}
class ReflectPoint{
privateintx;
publicinty;
public
Stringstr1 ="basketball";
protected
Stringstr2 ="aaaaaaaaaaCCCCCCCC";
public
Stringstr3 ="ababababa";
public
ReflectPoint(int x,
int y) {
super();
this.x
= x;
this.y
= y;
}
public
String toString(){
returnstr1+" "+str2+" "+str3;
}
}
18、成员方法的反射(Method类)
强调一下,Method类的实例对象是类中的方法,而不是对象中的方法
1、 Method类代表某个类中的一个成员方法
2、 得到类中的某个方法
Method charAt = Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);
3、 调用方法
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str,1))
如果传递给Method对象的invoke()方法的第一个参数为null,那就说明Method对象对应的是一个静态方法
4、 jdk1.4与jdk1.5在invoke方法上的区别
JDK1.5:public
Object invoke(Object obj, Object……args)
JDK1.4:public
Object invoke(Object obj,Object[ ]args)
Jdk1.5为了能够兼容jdk1.4,所以jdk1.5也会按照jdk1.4的语法使用invoke方法。需要将一个数组作为参数传递给invoke方法时,数组中每个元素分别对应被调用方法中的一个元素。故,调用charAt方法的代码也可以用jdk1.4改写为charAt.invoke(
“str”,new Object[]{1})
总结:Jdk1.4与Jdk1.5在反射的地方许多方法都不相同,1.4用数组,1.5用可变参数列表
专家模式:谁拥有数据,谁就是干这个事儿的专家,那么这个方法就应该分配给谁。
示例代码:
/**Method类*/RefectTest.java类中
Method charAt = str.getClass().getMethod("charAt",int.class);
System.out.println(charAt.invoke(str,
1));
System.out.println(charAt.invoke(str,new
Object[]{2}));//用jdk1.4的方式进行调用,Object数组长度为1
//invoke:对带有指定参数的指定对象调用由此
Method 对象表示的底层方法。
//如果底层方法是静态的,那么可以忽略指定的obj
参数。该参数可以为 null。因为静态方法时不需要对象的!
System.out.println(str.getClass().getMethod("valueOf",float.class).invoke(null,
12.3f));//12.3
19、对接收数组参数的成员方法进行反射(深入理解Method的调用)
目标:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法?此处不用普通方式调用,而用反射方式调用,为什么?
答:关于那个问号的解释:我的源程序根本就不知道执行那个类,而执行的类是根据参数来决定的,你告诉我执行A类,我就执行A类,你告诉我执行B类,我就执行B类。一句话总结:用反射的方式去调用某一个类的main方法的时候,这个类是未知的,可变的,而不是固定的,在这种情况下用普通的方式调用某个类的主方法是行不通的!
问题:invoke方法中的参数问题?
答:启动Java程序的main方法的参数是一个字符串数组,即public
static void main(String args[]),通过反射采用者个main方法时,如果为invoke方法传递参数呢?按jdk1.5的说法,整个数组时一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底用那种语法惊醒处理呢?jdk1.5要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用main
Method.invoke(null,new String[]{“XXX”},javac只能把它当做jdk1.4的语法进行理解,而不是把它当做jdk1.5的语法进行解释,因此会出现参数类型不对的问题
解决方案:
//第一种:将字符串转换成Object对象。注意每一个的数组父类都是Object。
//就相当于跟编译器说:我是一个Object对象不是一个数组,不要给我拆包了!
mainMethod.invoke(null,
(Object)new String[]{"abc","def","ghi"});
//第二种:将字符串数组作为Object数组中的一个元素
mainMethod.invoke(null,new
Object[]{new String[]{"abc","def","ghi"}});
之所以能这么包装,原因是,所有的数组类型的父类都是Object。
示例代码:
package staticImport.cn.itcast.day1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
publicclass
RefectTest {
publicstaticvoid
main(String args[])throws Exception {
/**Method类*/
Method charAt = str.getClass().getMethod("charAt",int.class);
System.out.println(charAt.invoke(str,
1));
System.out.println(charAt.invoke(str,new
Object[]{2}));//用jdk1.4的方式进行调用,Object数组长度为1
//invoke:对带有指定参数的指定对象调用由此
Method 对象表示的底层方法。
//如果底层方法是静态的,那么可以忽略指定的obj
参数。该参数可以为 null。因为静态方法时不需要对象的!
System.out.println(str.getClass().getMethod("valueOf",float.class).invoke(null,
12.3f));
/**Method的高级应用:
写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法?*/
//常用方式:TestArguments.main(new
String[]{"abc","def","ghi"});
String startingMainClass = args[0];
//参数为将要运行的java类名,main方法的参数为字符串数组
Method mainMethod = Class.forName(startingMainClass).getMethod("main",
String[].class);
//invoke为方法的调用,main方法为static方法,所以第一个参数为null
//第一种:将字符串转换成Object对象。注意每一个的数组父类都是Object。
//就相当于跟编译器说:我是一个Object对象不是一个数组,不要给我拆包了!
mainMethod.invoke(null,
(Object)new String[]{"abc","def","ghi"});
//第二种:将字符串数组作为Object数组中的一个元素
mainMethod.invoke(null,new
Object[]{new String[]{"abc","def","ghi"}});
}
}
class TestArguments{
publicstaticvoid
main(String args[]){
for(String
arg :args){
System.out.println(arg);
}
}
}
------- android培训、java培训、期待与您交流! ----------
相关文章推荐
- 黑马程序员_Java高新技术——反射和内省(第8篇)
- 黑马程序员_java学习日记_Java高新技术_反射
- 黑马程序员—JAVA高新技术之反射
- 黑马程序员——Java高新技术---反射
- 黑马程序员---java高新技术之反射
- 黑马程序员-java高新技术(反射)
- 黑马程序员--java高新技术--反射的深入讲解
- 黑马程序员_java高新技术(1)枚举、反射、内省
- 黑马程序员_java学习日记_Java高新技术_反射(二)
- 黑马程序员 java高新技术<二>--java5的枚举、反射的深入讲解
- 黑马程序员________Java高新技术之反射机制及枚举注释
- 黑马程序员_java高新技术(3)反射
- 黑马程序员--java高新技术----反射
- 黑马程序员_Java高新技术:反射
- 黑马程序员——JAVA高新技术---反射--概述,类中构造方法、字段、方法和数组的反射,框架原理,JavaBean简述
- 黑马程序员java高新技术——反射
- 黑马程序员 Java高新技术 反射总结
- 【黑马程序员】张孝祥Java高新技术_装箱拆箱、枚举、反射
- 黑马程序员——Java高新技术_反射
- 黑马程序员_Java高新技术(静态导入、可变参数、增强for循环、自动拆装箱、枚举、反射)