Class类的使用
Class类比较特殊,也比较难理解一些,所有类都是它的实例对象。我们用代码来理解一下:
public class ClassDemo {
public static void main(String[] args){
Person person = new Person();
}
}
class Person{}
普通的person是Person类的实例对象,同时Person这个类也是Class类的一个实例对象。当然Class类的实例对象不是new出来,它有三种表示方式,我们来看一下:
第一种:
在知道类名的情况下,调用该类的隐式的静态成员变量class
。
Class c1 = Person.class;
第二种:
在知道实例对象名的情况下调用对象的getClass()
方法。
Class c2 = person.getClass();
可以这么说,c1、c2表示了Person类的类类型。
第三种:
通过class类的forName()方法创建,但是需要捕获异常。
Class c3 = null;
try {
c3 = Class.forName("Person");
}catch (ClassNotFoundException e){
e.printStackTrace();
}
最后打印可以看到三种方法创建的对象是完全相等的。
System.out.println(c1 == c2 && c2 == c3); //true
我们也完全可以通过类的类类型创建该类的实例对象,调用类类型的newInstance()方法,这里需要做一下类型强转,而且需要捕获两个异常。
先给Person类中添加一个方法,用来测试
class Person{
public void show(){
System.out.println("通过类类型也可以创建实例对象鸭");
}
}
创建出实例对象后调用show()方法,可以看到正常打印。
try {
Person person1 = (Person) c1.newInstance();
person1.show();
}catch (InstantiationException e){
e.printStackTrace();
}catch (IllegalAccessException e){
e.printStackTrace();
}
Class类还提供了一堆获取成员信息的方法,可以看文档进行了解。(成员方法、变量、构造方法)
动态加载类
之前我们 通过new关键字创建对象属于静态加载,在编译时就要加载所有的类,如果一个有问题就会影响整个程序。那么能不能再调用到的时候再去加载类呢?答案是肯定的,这就是我们要说的动态加载。
不使用动态加载的例子:
if("Man".equals(args[0])){
Man man = new Man();
}
if("Woman".equals(args[0])){
Woman woman = new Woman();
}
这里args[0]
是一个命令行参数,动态传递进来的,这段代码就要求两个类都得存在,如果有一个不存在即使用不到这个类也会影响整个程序。我们用动态加载可以很好的避免这一点:
try{
Class c = Class.forName(args[0]);
Person person = (Person)c.newInstance();
}
这里我们不知道传递进来的是什么类型的,在强转类型时怎么办呢?在创建所有要用到的类(比如Man类实现Person接口)的时候统一实现Person接口即可(泛型)。这样只有用到才会调用此类。
方法反射
先写一个简单的反射了解一下:
class Person{
public void show(){
System.out.println("无参方法");
}
public void show(int a, int b){
System.out.println(a+b);
}
}
Person person = new Person();
Class c = person.getClass();
try {
// Method method = c.getMethod("show", new Class[]{int.class, int.class});
Method method = c.getMethod("show", int.class, int.class);
method.invoke(person, 2, 3);
Method method1 = c.getMethod("show");
method1.invoke(person);
}catch (Exception e){
e.printStackTrace();
}
-
先通过前面说过的三种方法获取到类的类类型,这里就是c。
-
通过getMethod()方法获取到类的方法,第一个参数是方法名,后面的参数可以是一个参数数组(注释掉部分),也可以直接把参数全部写出来(没有参数可以不写,也可以写空数组)。
-
使用方法对象的invoke方法来调用该类的方法,第一个参数是类的实例对象,后面参数和getMethod()写法一样。
-
可以看到两个方法都被执行了。
网友评论