获取类类型三种方式

面向对象的世界——万事万物皆对象

在面向对象的世界里,我们说万事万物皆对象。在Java语言中,只有两样不是面向对象:普通数据类型和java中的静态。

  • 普通数据类型:例如  int a=5;  这就不是一个对象。但是普通数据类型都有封装类来弥补这个缺陷。
  • java中的静态:不论是静态成员变量还是方法,java中的静态东西并不是属于某个对象,而是属于某个类。

所以在面向对象的世界里,最好万事万物都看做对象。

 

Class类的对象

既然万事万物皆对象,那么每写的一个类是不是一个对象呢?当然,所写的任何一个类都属于对象。那么这些类都是谁的对象呢?其实这些类都是java.lang.Class类的实例对象。比如:

我们写了一个Student的类,那么这个类是不是一个对象?当然是一个对象。那么是谁的对象呢?Class类的对象。既然如此那么我们是不是就可以用

 

Class classStu=new Class()

 

这种构造方法的方式来表示这个Class类的对象呢?答案是否定的。虽然每写的每一个类都是Class类的对象,但是这个对象的表达方式比较麻烦。

 

创建Class类对象

看一下Class类中的构造方法:

 1      /*
 2       * Private constructor. Only the Java Virtual Machine creates Class objects.
 3       * This constructor is not used and prevents the default constructor being
 4       * generated.
 5       */
 6      private Class(ClassLoader loader) {
 7          // Initialize final field for classLoader.  The initialization value of non-null
 8          // prevents future JIT optimizations from assuming this final field is null.
 9          classLoader = loader;
10 }
说明
  1. Only the java Virtual Machine creates Class objcts:只能由Java虚拟机来创建Class类对象。
  2. Class类的构造函数使用的是private私有的方法,因此不可以被外部引用。

所以不能天真的像创建其他对象一样通过Class类的构造函数来创建Class类的对象。那么该如何创建Class类的对象呢?有三种方式:

 

Student.java:创建Student类,并且实例化Student类的一个对象student。如何创建Student类型的Class类的对象?

1 package com.xxj;
2 
3 public class ClassDemo01 {
4     public static void main(String[] args) {
5         Student student=new Student();//Student类的实例对象
6     }
7 }
8 class Student{}

 

第一种:通过  类名.Class  方式

Class<?> class1=Student.class;

通过类名.Class的方式就可以创建了一个Class类的对象。这种方式还透露了一个信息:任何一个类中隐藏了一个静态的成员变量class。

第二种:通过该类的实例对象的getClass()方法获取Class类的实例对象

1 //            创建Student类的对象student
2         Student student=new Student();
3 //            利用该类对象的getClass方法获取Class类的实例
4         Class<?> class2=student.getClass();

Q:getClass()这个方法又是从哪个地方冒出来的呢?

A:如果一个类没有明确指明继承哪个类,就会默认继承Object。在Object类中有个:public final native Class<?> getClass();方法。

 

说明:

1、student代表的是Student类的实例对象,class1与class2都代表的是Class类的实例对象。

官方对class1、class2的解释:

class1和class2都表示了Student类的类类型(class type)。

Student类的类类型:本身Student类就是一个Class类的类型的对象。

可以先看一个例子来帮助理解:上面的student是Student类型。同理,Student类是Class类型的,转个弯即Student类是类类型的。所以class1,class2就是类类型,然而为了加以区分不同的类类型,我们称之为该类的类类型。因此class1与class2成为Student类的类类型。

Student类的对象是student。

Student类的Class对象是:class1,class2。(Student类的类类型)

 

第三种方式创建Student类的类类型:通过forName(“全限定类名”)

1         Class class3=null;
2         try {
3             class3=Class.forName("com.xxj.Student");//加类的全称    
4         } catch (ClassNotFoundException e) {
5             e.printStackTrace();
6         }

这里面必须加上完整的类的全名包名.类名。因为这里需要输入类的名称,但是防止输入的错误,所以这里面有ClassNotFoundException异常。

问题:上面我们已经实例化出了三个Student类的类类型对象,那么这三个对象是什么?有什么关系?是否相等呢?

1 System.out.println("class1==class2:"+(class1==class2));
2 System.out.println("class2==class3:"+(class2==class3));
3 System.out.println("class1==class3:"+(class1==class3));
4 System.out.println("student1==student2:"+(student==student2));
5 System.out.println("class1为:"+class1);
6 System.out.println("student1为:"+student+",student2为:"+student2);

运行结果:

 

1 class1==class2:true
2 class2==class3:true
3 class1==class3:true
4 student1==student2:false
5 class1为:class com.xxj.Student
6 student1为:com.xxj.Student@2a139a55,student2为:com.xxj.Student@15db9742

 

 

 

说明:一个类只可能是Class类的一个实例对象,也就是说不管创建了多少该类的类类型对象,也不管用了何种方式创建该类的类类型对象,最终都是同一个。

 

该类的类类型创建该类的实例对象(说的简单些就是通过class1、class2或者class3来创建Student的实例对象。)

说明:如果是A类的类类型创建出来的就是A类的对象,如果是B类的类类型创建出来的就是B类的对象。也因此导致java源码并不知道具体是哪个类的类类型来创建实例对象的,所以通过该类的类类型创建该类的实例对象Java直接返回一个Object类型,这样就需要通过强制的类型转换。

 

通过Class类中的newInstance()方法来定义类实例化的对象。


public Object newInstance() throw InstantiationException,IllegalAccessException

操作代码

 1   try {
 2       Student student3=(Student)class1.newInstance();//通过newInstance方法创建该类的类类型对应该类的实例对象
 3       Student student4=(Student)class2.newInstance();        
 4       System.out.println("student3为:"+student3);
 5       System.out.println("student4为:"+student4);
 6       student3.print();
 7   } catch (InstantiationException e) {
 8       e.printStackTrace();
 9   } catch (IllegalAccessException e) {
10       e.printStackTrace();
11   }

运行结果:

student3为:com.xxj.Student@6d06d69c
student4为:com.xxj.Student@7852e922
Student print 

注意:使用newInstance方法创建实例,要求类中要有个无参的构造函数,因为newInstance()方法会默认的调用无参的构造函数。

问题如果类中没有无参的构造函数该如何处理呢?可以通过public T newInstance(Object... initargs) throws方法来解决此问题。

1 class Student{
2     public Student(String name,int age,String school){
3             
4     }
5     void print(){
6         System.out.println("Student print ");
7     }
8 }

 

此Student类中就没有无参的构造函数,我们还是上面的代码运行发现报错如下:初始化异常!

java.lang.InstantiationException: com.xxj.Student
at java.lang.Class.newInstance(Unknown Source)
at com.xxj.ClassDemo01.main(ClassDemo01.java:72)
Caused by: java.lang.NoSuchMethodException: com.xxj.Student.<init>()
at java.lang.Class.getConstructor0(Unknown Source)
... 2 more

 解决方法

1 Student student3=(Student)class1.getConstructors()[0].newInstance(new Object[]{"Tom",19,"南工天下"});
2 Student student4=(Student)class3.getConstructors()[0].newInstance("3QC",20,"水木清华");
3 student4.print();

因为这里面没有一个默认的构造方法,所以不可以采用类类型直接调用newInstance()方法实例化对象,只能先通过getConstructors方法获取全部的构造函数,然后找到匹配的构造函数使用newInstance方法传入参数才可以实例化对象。

 

完整代码:

package com.xxj;

public class ClassDemo01 {

    public static void main(String[] args) {
        Student student=new Student();
        Student student2=new Student();
        
        Class<?> class1=Student.class;
        Class<?> class2=student.getClass();
        Class class3=null;
        try {
            class3=Class.forName("com.xxj.Student");//加类的全称    
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
         
        System.out.println("class1==class2:"+(class1==class2));//返回true
        System.out.println("class2==class3:"+(class2==class3));
        System.out.println("class1==class3:"+(class1==class3));
        System.out.println("class1为:"+class1);
        System.out.println("student1==student2:"+(student==student2));
        System.out.println("student1为:"+student+",student2为:"+student2);
    
        try {
            Student student3=(Student)class1.newInstance();
            Student student4=(Student)class2.newInstance();
            System.out.println("student3==student4:"+(student3==student4));            
            System.out.println("student3为:"+student3);
            System.out.println("student4为:"+student4);
            student3.print();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
class Student{
    void print(){
        System.out.println("Student print ");
    }
}

运行结果:

class1==class2:true
class2==class3:true     
class1==class3:true     
class1为:class com.xxj.Student
student1==student2:false
student1为:com.xxj.Student@2a139a55,student2为:com.xxj.Student@15db9742
student3==student4:false
student3为:com.xxj.Student@6d06d69c
student4为:com.xxj.Student@7852e922
Student print

 

END.

posted @ 2017-10-27 09:47  GaJa  阅读(3269)  评论(0编辑  收藏  举报