【Java笔记】反射机制中用Class操作的一些演示

package Test_01;
import org.junit.Test;


public class Test_01 {
@Test
	public void Dome_05() throws InstantiationException, IllegalAccessException{
		Class cc1=Cat.class;
		Cat cat=(Cat) cc1.newInstance();//这个方法是通过类对象调用构造器来创建类的实例对象;
		cat.age=3;
		
	}
}
package Test_01;

public class Cat extends Animals{
	 String name;
	 int age;
	 int legs;
	 Cat(){}
	
}
成功创建Cat对象


我们来看一下newInstance的API解释:

newInstance

public T newInstance()
              throws InstantiationException,
                     IllegalAccessException

创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的 new 表达式实例化该类。如果该类尚未初始化,则初始化这个类。



实际上newInstance就是通过调用无参构造器来创建对象,我如果把Cat中的构造器私有化:

package Test_01;

public class Cat extends Animals{
	 String name;
	 int age;
	 int legs;
	private Cat(){}
}
运行时报错

所以,用newInstance必须保证在类里一定要有一个无参构造器;

上面是newInstance来创建对象的方法,其实和直接new对象没有什么很大的区别;下面我们来看一下Class的真正强大之处:

package Test_01;

public class Cat extends Animals{
	 private String name;
	 private int age;
	 private int legs;
	 private Cat(){}
	 private Cat(String name,int age,int legs){
		this.age=age;
		this.legs=legs;
		this.name=name;
	}
}
可以看到我完全把Cat类封装,也没有实行单例模式,也没有设置get、set方法,按理来说已经没办法实例化它的对象了,但是用Class的反射机制可以通过调用方法来返回Constructor中的方法来实例化它!

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

@Test
	public void Dome_05() throws InstantiationException, IllegalAccessException, Exception, Throwable{
		Class<Cat> cc = Cat.class;
		//通过Class类中的getDeclaredConstructor可以获得私有化的构造器
			Constructor<Cat> constructor =cc.getDeclaredConstructor(String.class,int.class,int.class);
			//把constructor的权限设成true
			constructor.setAccessible(true);
			//下面就可以通过构造器来实例化对象了
			Cat gaffey=constructor.newInstance("gaffey",3,4);
			System.out.println(gaffey);					
	}
输出结果:Test_01.Cat@14514713

打印出了对象的地址,说明成功创建了一个对象;注意:此时就算是创建了对象,我的Cat的成员变量仍是全部私有化的,所以也不能通过对象对成员变量进行操作;

在jdk的API中:

Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
          返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 
 Constructor<?>[] getDeclaredConstructors() 
          返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。 

可知,我们通过控制传入参数的多少来控制调哪一个构造器,要注意的是,如果我们传参数,传入的必须是类对象,这个类不是我们通常说的类或创建的类(小写的class),而是大写的Class,是jdk中存在的单例模式的Class,所有的小写的class类,都可以是这个大写的Class类的对象,比如我们要传入String,就应该传入String的class属性,用“String.class";

看一下Constructor类,里面也有一个newInstance方法:

newInstance
public T newInstance(Object... initargs)

throws InstantiationException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。个别参数会自动解包,以匹配基本形参,必要时,基本参数和引用参数都要进行方法调用转换。
如果底层构造方法所需形参数为 0,则所提供的 initargs 数组的长度可能为 0 或 null。

如果构造方法的声明类是非静态上下文的内部类,则构造方法的第一个参数需要是封闭实例;请参阅Java 语言规范 第 15.9.3 节。

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

如果构造方法正常完成,则返回新创建且已初始化的实例。

显然通过构建Constructor就可以调用有参的构造器了,我上面的那篇代码中也演示了用Constructor的newInstance方法来调用构造器实例化对象;




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值