A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 黄业凌 中级黑马   /  2012-4-28 12:59  /  5249 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

package cm.day6.reverberate;
import  java.lang.reflect.Field;
import  java.lang.reflect.Method;
import  java.lang.reflect.Constructor;
public class ReflectDemo {

        /**
         * @param args
         */
        public static void main(String[] args)throws Exception{
                Task task = new Task("abc","aac",99,'c');
                System.out.print("当前值");
                task.show();
                /*
                 *Field修改String类型变量
                 */
                Field[] fields = task.getClass().getFields();
                for(Field fie : fields){
                        System.out.println(fie.getName());
                        if(fie.getType() == String.class){
                                String value = (String)fie.get(task);
                                String newValue = value.replace("a", "x");
                                fie.set(task,newValue);
                        }
                        if(fie.getType() == char.class){
                                char vachar = fie.getChar(task);
                                vachar = 'x';
                                fie.setChar(task, vachar);
                        }
                        if(fie.getType() == int.class){
                                int i = fie.getInt(task);
                                int a = 999;
                                fie.setInt(task, a);
                        }
                }
                System.out.print("修改值");
                task.show();
               
                /*
                 * Method方法获取指定类方法
                 */
                //获得一个String类charAt(int)方法
                Method method = String.class.getMethod("charAt",int.class);
                String str = "abcde";
                System.out.println(method.invoke(str, 2));
               
                /*
                 * Constructor方法获取指定类构造方法
                 */
                Class ct = Class.forName("cm.day6.reverberate.Task");
                //包名为:
                Package p = ct.getPackage();
                System.out.println("包名为:" + p);
                //获取指定构造方法
                Constructor c = ct.getDeclaredConstructor(String.class,String.class,int.class,char.class);
                Integer a = (Integer)c.newInstance(new Task("avv","a",0,'x'));//newInstance()方法报错传入的参数不对
                System.out.println(a.toString());
        //System.out.println(ct);
        }

}

class Task{
        public int  num;
        public char  nums;
        public String demo1;
        public String demo2;

        Task(String demo1,String demo2,int num,char nums){
                this.demo1 = demo1;
                this.demo2 = demo2;
                this.num = num;
                this.nums = nums;
        }
       
        Task(){
                this.num = num;
        }
       
        public void show(){
                System.out.println("demo1:" + demo1 + "\tdemo2:" + demo2 + "\tnum:" + num + "\tnums:" + nums);
        }
       
}

报错
java.lang.IllegalArgumentException: wrong number of arguments
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at cm.day6.reverberate.ReflectDemo.main(ReflectDemo.java:56)


谁说下newInstance()方法 谢谢

7 个回复

倒序浏览
  Integer a = (Integer)c.newInstance(new Task("avv","a",0,'x'));//你强转为Integer类型的,可你传入的类型也太杂了吧
回复 使用道具 举报
Integer a = (Integer)c.newInstance(new Task("avv","a",0,'x'));//传入的参数不对所以报的是非法参数,newInstance是传入是的可变参数。c.newInstance(("avv","a",0,'x');
Task ta=(Task )c.newInstance("avv","a",0,'x');这样子应该可以了。
回复 使用道具 举报
newInstance
public T newInstance(Object... initargs)
              throws InstantiationException,
                     IllegalAccessException,
                     IllegalArgumentException,
                     InvocationTargetException使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。个别参数会自动解包,以匹配基本形参,必要时,基本参数和引用参数都要进行方法调用转换。
如果基础构造方法所需形参数为 0,则所提供的 initargs 数组的长度可能为 0 或 null。

如果所需的访问检查和参数检查获得成功并且实例化继续进行,这时构造方法的声明类尚未初始化,则初始化这个类。

如果构造方法正常完成,则返回新创建且已初始化的实例。
抛出:
IllegalAccessException - 如果此 Constructor 对象实施 Java 语言访问控制并且基础构造方法是不可访问的。
IllegalArgumentException - 如果实参和形参的数量不同;如果基本参数的解包转换失败;如果在可能的解包后,无法通过方法调用转换将参数值转换为相应的形参类型;如果此构造方法属于枚举类型。
InstantiationException - 如果声明基础构造方法的类表示抽象类。
InvocationTargetException - 如果基础构造方法抛出异常。
ExceptionInInitializerError - 如果此方法引发的初始化失败。
回复 使用道具 举报
使用newInstance()方法的时候:必须保证
1、这个类已经加载;
2、这个类已经连接了
而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载java API的那个加载器。
回复 使用道具 举报
Integer a = (Integer)c.newInstance(new Task("avv","a",0,'x'));
newInstance()传入的参数是一个可变参数,是构造函数的参数,你却传入一个对象。
逻辑不对吧?
回复 使用道具 举报
孙天 黑马帝 2012-4-28 20:21:33
7#
class类中的newInstance方法来是用来完成该类实例的创建,你这个task类型不能转成integer吧
附:
获取指定的字节码文件中的属性。字段:
1,获取指定名称字节码文件对象
Class clazz=Class.forName("cn.itcast.c.bean.Person");
2,通过该字节码文件对象的方法获取字节码文件中的字段
Field[] fields=clazz.getFields();
for(Field field: fields){
syso(field)
}
    获得私有的字段:
fields=clazz.getDeclareFields();
for(Field field : fields){
syso(field)
}

获取指定字段:
Class clazz=Class.forName(....)
Field field=clazz.getField("name");
获取字段值,但是对于非静态的字段必须要有所属的对象。既然需要该类对象,就可以通过class类中的newInstance方法来完成该类实例的创建
Object obi=clazz.newInstance();
给指定字段赋值:
field.set(obj,"旺财");
Object value=field.get(obj);
sys(value);

获取私有字段:
Class clazz=Class.forName("cn.itcast.c.bean.Person");
Field field=class.getDeclareField("age");
Object obj=clazz.newInstance();
取消对权限的检查,暴力访问:
field.setAccessible(true);
field.set(obj,34);
Objcet value=field.get(obj);
sys(value);


获取构造器:
Class clazz=Class.forName("cn.itcast.c.bean.Person");
先获取指定的构造器:
Constructor cons=clazz.getConstructor(String.class);
Objcet obj=cons.newinstance("小强");
Field field=clazz.getField("name");
Object value=field.get(obj);
sys(value)

获取方法:method
获取所有方法:
Class clazz=Class.forName("....");
Method[] methods=clazz.getMethods();
methods=clazz.getDeclareMethods();
for()
获取私有方法:
Class clazz=Class.forName(...);
Method method=clazz.getDecalerMethod("privateShow",null);
Object obj=clazz.newInstance();
method.setAccessible(true);
method.invoke(obj,null);
获取静态方法:
Class clazz=Class.forName(...);
Method method=class.getMethod("staticShow",null);
method.invoke(null,null);           没有obj
获取一个带参数的方法:
Calss clazz=Class.forName("...");
Method method =clazz.getMethod("paraShow",String.class,int.class);
Object obj=clazz.newInstance();
method.invoke(obj,"xiaoming",89);
回复 使用道具 举报
你下面的这段代码有问题:
  Constructor c = ct.getDeclaredConstructor(String.class,String.class,int.class,char.class);
                Integer a = (Integer)c.newInstance(new Task("avv","a",0,'x'));//newInstance()方法报错传入的参数不对
                System.out.println(a.toString());
ct明明是 Class ct = Class.forName("cm.day6.reverberate.Task");是Task类型的对象,为什么你给人家强转为(Integer)类型呢,显然这地方是不对的,同时,Task类型的构造方法是接收可变参数的,也就是前两个参数是String类型的,第三个是int 类型,第四个是char类型的,但是你传入的是new(。。。)一个对象,这个地方也是不对的
应该改成这样的  Task  task = (task)c.newInstance("avv","a",0,'x')                    如果你把构造方法Constructor的泛型类型改为Task的,前面的那个代码也就不用强制类型转换了(楼主你懂的)。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马