JAVA類型信息——Class對象
一、RTTI概要
1、類型信息RTTI :即對象和類的信息,例如類的名字、繼承的基類、實現的接口等。
2、類型信息的作用:程序員可以在程序運行時發現和使用類型信息。
3、RTTI真正含義:運行時,識別一個對象的類型。
4、如何在程序運行時識別對象和類的信息?
1)傳統RTTI:即在編譯時已知道了所有的類型。
2)反射機制:在程序運行時發現和使用類的信息。
5、RTTI的使用
import java.util.*; //List支持泛型
//import java.awt.List; 不支持泛型
import java.util.Arrays;
abstract class Shapes{
void draw() {System.out.println(this + ".draw()");}
abstract public String toString();
}
class Circle extends Shapes{
public String toString() {return "Circle";}
}
class Triangle extends Shapes{
public String toString() {return "Triangle";}
}
class Square extends Shapes{
public String toString() {return "Square";}
}
class Test{
public static List<Shapes> getList(){
List<Shapes> list_aShapes = Arrays.asList(new Circle() , new Square(), new Triangle());
return list_aShapes;
}
}
public class Shape {
public static void main(String[] args) {
List<Shapes> list_aShapes = Test.getList();
for(Shapes ob_aShapes : list_aShapes) {
ob_aShapes.draw();
}
}
}
運行結果:Circle.draw()
Square.draw()
Triangle.draw()
結果分析:(1)toString()都繼承Object類的toSting(),派生類的toString()都會覆蓋基類的該方法。
(2)Shapes.draw()中的this間接調用toString()。
(3)假設Test類是服務器端提供給客戶端使用的一個類,客戶端調用該類的方法(這里main()調用)獲得一個泛化引用,顯然,客戶端並不知道泛化引用中的確切類型,而程序員需要使用到某一個確切類型對象,這時,我們就需要到RTTI。在上面的例子中,我們只是打印出泛化引用的所有類型。
二、Class對象
| Class對象概述 |
(1)持有RTTI信息 (2)每個類都有一個Class對象,每當編譯一個新類就產生一個Class對象。 (3) Class引用總是指向某個Class對象。Class引用表示的就是它所指向的對象的確切類型,而該對象便是Class類的一個對象。 () |
||
| forName() |
(1) 獲取Class對象的一個引用,但引用的類還沒有加載(該類的第一個對象沒有生成)就加載了這個類. (2) 為了產生Class引用,forName()立即就進行了初始化。 |
||
| Object-getClass() |
獲取Class對象的一個引用,返回表示該對象的實際類型的Class引用。 |
||
| getName() |
獲取全限定的類名(包括包名),即類的完整名字。 |
||
| getSimpleName() |
獲取類名(不包括包名) |
||
| getCanonicalName() |
獲取全限定的類名(包括包名) |
||
| isInterface() |
判斷Class對象是否是表示一個接口 |
||
| getInterface() |
返回Class對象,表示Class對象所引用的類所實現的所有接口。 |
||
| getSupercalss() |
返回Class對象,表示Class對象所引用的類所繼承的直接基類。應用該方法可在運行時發現一個對象完整的繼承結構。 |
||
| newInstance() |
返回一個Oject對象,是實現“虛擬構造器”的一種途徑。 “虛擬構造器”:我不知道你的確切的類型,但無論如何都要正確創建你自己。 使用該方法創建的類,必須帶有默認的構造器。 |
||
| cast() |
接受一個對象為參數,並將其轉型為Class引用的類型。該法一般是在無法使用普通轉型的情況下使用。 |
||
| getClassLoader() |
返回該類的類加載器。 |
||
| getComponentType() |
返回表示數組組件類型的Class。 |
||
| isArray() |
判定此 Class 對象是否表示一個數組類。 |
||
|
|
|||
| 類字面常量 |
(1)一種用來生成對Class對象引用的方法。 (2)相對forName()而言,效率更高,而且不會立即引發初始化。 (3)方法:className.class;。 (4)既可用於普通類,也可用於接口、數組、基本數據類型。 |
||
|
|
…………等價於………… |
||
|
|
boolean.class |
Boolean.class |
|
|
|
char.class |
Char.class |
|
|
|
byte.class |
Byte.class |
|
|
|
short.class |
Short.class |
|
|
|
int.class |
Integer.class |
|
|
|
long.class |
Long.class |
|
|
|
float.class |
Float.class |
|
|
|
double.class |
Double.class |
|
|
|
void.class |
Void.class |
|
|
|
|
|
|
|
|
|||
| 泛化的Class引用 |
(1)實現方法:使用通配符“?”。 (2)Class<?>優於Class,即便他們是等價的。 (3)Class<?>的好處是明確地告訴編譯器你選擇了非具體的類版本,而不是由於碰巧或者疏忽而使用了一個非具體的類引用。 (4)創建一個范圍:創建一個Class引用 ,使它被限定為某種類型<className>;或該類型的任何子類型,< ? extends superClass>;或者該類型的超類,< ? super super sunClassName> |
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.lang.Class;
import java.lang.reflect.Constructor;
interface Iterface1{}
interface Iterface2{}
abstract class SuperClass{
SuperClass(){};
SuperClass(int i){}
static {System.out.println("creating SuperClass");}
}
class SunClass extends SuperClass implements Iterface1, Iterface2{
SunClass(){super(1);}
static {System.out.println("creating SunClass");}
}
class SunClass1 extends SuperClass implements Iterface1, Iterface2{
SunClass1(){super(1);}
static {System.out.println("creating SunClass1");}
}
public class ClassObject {
static void printInfo(Class cc) {
System.out.println("Class name:" + cc.getName()
+ " is Interface : " + cc.isInterface()
+" Simple name : " + cc.getSimpleName()
+ " Canonical name : " + cc.getCanonicalName());
}
public static void main(String[] args) {
System.out.println("/////forName()與類字面常量////////");
Class ob_aClass = null;
//對類的引用不引發初始化
Class ob_cClass = SuperClass.class;
System.out.println("After creating SuperClass");
try {
//立即初始化類
ob_aClass = Class.forName("rtti.SunClass");
System.out.println("After creating SunClass");
System.out.println("///////////////////////////////////");
}catch(ClassNotFoundException e){
System.out.println("Can't find SunClass.");
System.exit(1);
}
printInfo(ob_aClass);
System.out.println("///////Class引用實現的接口///////");
for(Class face : ob_aClass.getInterfaces())
printInfo(face);
System.out.println("//////Class引用的基類////////");
Class ob_bClass = ob_aClass.getSuperclass();
printInfo(ob_bClass);
System.out.println("///////newInstance()///////");
Object ob_aObject = null;
try {
ob_aObject = ob_aClass.newInstance();
//運行剖出異常 newInstance()該法必須由Class.forName()調用
//ob_aObject = ob_bClass.newInstance();
}catch(InstantiationException e){
System.out.println("Can't instante.");
System.exit(1);
}catch(IllegalAccessException e){
System.out.println("Can't access.");
System.exit(1);
}
printInfo(ob_aObject.getClass());
System.out.println("//////Class引用的泛型////////");
Class <? extends SuperClass> ob_dClass = SunClass.class;
printInfo(ob_dClass);
Class <? extends SuperClass> ob_eClass = SunClass1.class;
printInfo(ob_eClass);
//沒有類型轉換(Class<? super SunClass>),會出錯,上位知道原因?
Class<? super SunClass> ob_fClass = (Class<? super SunClass>)
ob_dClass.getSuperclass();
printInfo( ob_fClass);
}
}
運行結果:
creating SuperClass
creating SunClass
After creating SunClass
///////////////////////////////////
Class name:rtti.SunClass is Interface : false Simple name : SunClass Canonical name : rtti.SunClass
///////Class引用實現的接口///////
Class name:rtti.Iterface1 is Interface : true Simple name : Iterface1 Canonical name : rtti.Iterface1
Class name:rtti.Iterface2 is Interface : true Simple name : Iterface2 Canonical name : rtti.Iterface2
//////Class引用的基類////////
Class name:rtti.SuperClass is Interface : false Simple name : SuperClass Canonical name : rtti.SuperClass
///////newInstance()///////
Class name:rtti.SunClass is Interface : false Simple name : SunClass Canonical name : rtti.SunClass
//////Class引用的泛型////////
Class name:rtti.SunClass is Interface : false Simple name : SunClass Canonical name : rtti.SunClass
Class name:rtti.SunClass1 is Interface : false Simple name : SunClass1 Canonical name : rtti.SunClass1
Class name:rtti.SuperClass is Interface : false Simple name : SuperClass Canonical name : rtti.SuperClass
