面向对象的世界————万事万物皆对象
在面向对象的世界里,我们说万事万物皆对象。在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}
说明:
Only the java Virtual Machine creates Class objcts:只能由Java虚拟机来创建Class类对象。
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.