getClass(),class属性和getName()解析getGenericSuperclass

来源:互联网 发布:网络诈骗安全选择题 编辑:程序博客网 时间:2024/06/05 10:24
A   a; a.getClass(); 将返回a对象的信息描述,当然这些信息都是动态的,比如a对象的某个属性有什么值阿等等,你可以在程序运行时通过写代码动态的获得这些信息。getClass().getName()是用来返回Class对象所代表的具体对象的名称。</span>

<span style="font-size:18px;">public class Person<T> {}import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;public class Student extends Person<Student> {public static void main(String[] args) {Student st=new Student();Class clazz=st.getClass();//getSuperclass()获得该类的父类System.out.println(clazz.getSuperclass());//getGenericSuperclass()获得带有泛型的父类//Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。Type type=clazz.getGenericSuperclass();System.out.println(type);//ParameterizedType参数化类型,即泛型ParameterizedType p=(ParameterizedType)type;//getActualTypeArguments获取参数化类型的数组,泛型可能有多个Class c=(Class) p.getActualTypeArguments()[0];System.out.println(c);}}打印结果:class com.test.Personcom.test.Person<com.test.Student>class com.test.Student</span>

getClass方法:
类型:public final Class<? extends Object> getClass()
功能:返回该对象的运行时类的java.lang.Class对象(API上的解释)
有方法类型可以知道,该方法只能由类的实例变量调用
例子:

[java] view plaincopy
  1. JButton b1 = new JButton("button1");  
  2. System.out.println(b1.getClass());  

输出:
class javax.swing.JButton

class属性
当你要获得一个类的Class对象时(作函数参数的时候),你不能调用getClass方法,那你只能用类名.class来达到效果
例子:

 

 

[java] view plaincopy
  1. System.out.println(JButton.class);  

输出:
class javax.swing.JButton

getName方法:
类型:public String getName()
功能:以String形式返回次Class对象所表示的实体名称
例子:

[java] view plaincopy
  1. JButton b1 = new JButton("button1");  
  2. System.out.println(b1.getName());  

输出:
javax.swing.JButton

可以发现用class属性和getClass返回的输出是一样的,用getName返回的比前面两种少了class和一个空格。

 

.eclipse工具 可以按"."然后马上提示很多方法 供你选择
那他如何知道"."了以后有哪些方法?
他用的语法就是getClass().getMethods();

 

 

 

 

二、

.class其实是在java运行时就加载进去的

getClass()是运行程序时动态加载的

下面以例子说明:


 
  1. 首先建一个基类Baseclass  
  2.   
  3. package  classyongfa;  
  4.   
  5. public  class  Baseclass {  
  6.   
  7. private  String height;  
  8. public  String getHeight()  
  9. {  
  10.    return  height;  
  11. }  
  12.   
  13. public  void  setHeight(String height)  
  14. {  
  15.     
  16.    this .height=height;  
  17.     
  18. }  
  19. 下面是继承Baseclass类Extendclass  
  20.   
  21. package  classyongfa;  
  22.   
  23. public  class  Extendclass extends  Baseclass {  
  24.   
  25. private  String width;  
  26. public  String getWidth()  
  27. {  
  28.    return  width;  
  29. }  
  30.   
  31. public  void  setWidth(String width)  
  32. {  
  33.     
  34.    this .width=width;  
  35.     
  36. }  
  37. public  static  void  main(String[] arg0)  
  38. {  
  39.    Baseclass baseclass1=new  Extendclass();  
  40.    Baseclass baseclass2=new  Baseclass();  
  41.    System.out.println(baseclass1.getClass().getSimpleName());//实际运行的是继承类Extendclass   
  42.   
  43. System.out.println(baseclass2.getClass().getSimpleName());//实际运行的是Baseclass   
  44.   
  45.   
  46.    System.out.println(Baseclass.class .getSimpleName());//加载时类名   
  47. System.out.println(Extendclass.class .getSimpleName());//加载时类名   
  48.   
  49. }  
  50.   
  51. 结果是  
  52.   
  53. Extendclass  
  54. Baseclass  
  55. Baseclass  
  56. Extendclass

 

 

三、 四种获取Class对象的方法 Java反射机制

下面以一个具体的实例来说明。此实例来自《精通Hibernate 3.0 Java数据库持久层开发实践》一书。

先在com.hqh.reflect下建一个文件UseInfojava

package com.hqh.reflect;

public class UseInfo {

private Integer id;
private String userName;
private String password;

public Integer getId() {
   return id;
}

public void setId(Integer id) {
   this.id = id;
}

public String getUserName() {
   return userName;
}

public void setUserName(String userName) {
   this.userName = userName;
}

public String getPassword() {
   return password;
}

public void setPassword(String password) {
   this.password = password;
}

}

package com.hqh.reflect;

public class GetClassTest {

public static void main(String[] args) {
   GetClassTest test = new GetClassTest();
   if(test.ClassCheck())
    System.out.println("OK");

}

public boolean ClassCheck() {
   try {
    System.out.println("通过类本身获得对象");
    Class userClass = this.getClass() ;
    System.out.println(userClass.getName());
    System.out.println("===========");
   
    System.out.println("通过子类的实例获得父类对象");
    UseInfo useInfo = new UseInfo();
    userClass = useInfo.getClass();
    System.out.println(userClass.getName());
    Class subUserClass = userClass.getSuperclass() ;
    System.out.println(subUserClass.getName());
    System.out.println("===========");
   
    System.out.println("通过类名.class获取对象");
    Class forClass = com.hqh.reflect.UseInfo.class ;
    System.out.println(forClass.getName());
    System.out.println("===========");
   
    System.out.println("通过类名的字符串获取对象");
    Class forName = Class.forName("com.hqh.reflect.UseInfo") ;
    System.out.println(forName.getName());
    System.out.println("=============");
   
   } catch (Exception e) {
    e.printStackTrace();
    return false;
   }
   return true;
}
}


结果:

通过类本身获得对象
com.hqh.reflect.GetClassTest
===========
通过子类的实例获得父类对象
com.hqh.reflect.UseInfo
java.lang.Object
===========
通过类名.class获取对象
com.hqh.reflect.UseInfo
===========
通过类名的字符串获取对象
com.hqh.reflect.UseInfo
=============
OK



在初始化一个 类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法,一个是关键字外,最主要有什么区别?它们的区别在于创建对象的方 式不一样,前者是使用类加载机制,后者是创建一个新类。那么为什么会有两种创建对象方式?这主要考虑到软件的可伸缩、可扩展和可重用等软件设计思想。 

Java中工厂模式经常使用newInstance()方法来创建对象,因此从为什么要使用工厂模式上可以找到具体答案。 例如: 
class c = Class.forName(“Example”); 
factory = (ExampleInterface)c.newInstance(); 

其中ExampleInterface是Example的接口,可以写成如下形式: 
String className = "Example"; 
class c = Class.forName(className); 
factory = (ExampleInterface)c.newInstance(); 

进一步可以写成如下形式: 
String className = readfromXMlConfig;//从xml 配置文件中获得字符串 
class c = Class.forName(className); 
factory = (ExampleInterface)c.newInstance(); 

上面代码已经不存在Example的类名称,它的优点是,无论Example类怎么变化,上述代码不变,甚至可以更换Example的兄弟类Example2 , Example3 , Example4……,只要他们继承ExampleInterface就可以。 

从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。但是使用newInstance()方法的时候,就必须保证:1、这个 类已经加载;2、这个类已经连接了。而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载 java API的那个加载器。 

现在可以看出,newInstance()实际上是把new这个方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化。 这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。 

最后用最简单的描述来区分new关键字和newInstance()方法的区别: 
newInstance: 弱类型。低效率。只能调用无参构造。 
new: 强类型。相对高效。能调用任何public构造。

Class aClass = Class.forName(xxx.xx.xx);
Object anInstance = aClass.newInstance();


Class.forName("").newInstance()返回的是object
but there is some limit for this method to create instance
that is your class constructor should no contain parameters, and you should cast the instance manually.

Class Driver{
protected static Driver current;
public static Driver getDriver(){
return current;
}
}

Class MyDriver extends Driver{
static{
Driver.current=new MyDriver();
}
MyDriver(){}
}

用时:
Class.forName("MyDriver");
Driver d=Driver.getDriver();

有的jdbc连接数据库的写法里是Class.forName(xxx.xx.xx);而有一些:Class.forName(xxx.xx.xx).newInstance(),为什么会有这两种写法呢?

Class.forName(xxx.xx.xx) 返回的是一个类,
.newInstance() 后才创建一个对象

Class.forName(xxx.xx.xx);的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段

在JDBC规范中明确要求这个Driver类必须向DriverManager注册自己,即任何一个JDBC Driver的Driver类的代码都必须类似如下:
public class MyJDBCDriver implements Driver {
static {
DriverManager.registerDriver(new MyJDBCDriver());
}
}

所以我们在使用JDBC时只需要Class.forName(XXX.XXX);就可以了

we just want to load the driver to jvm only, but not need to user the instance of driver, so call Class.forName(xxx.xx.xx) is enough, if you call Class.forName(xxx.xx.xx).newInstance(), the result will same as calling Class.forName(xxx.xx.xx), because Class.forName(xxx.xx.xx).newInstance() will load driver first, and then create instance, but the instacne you will never use in usual, so you need not to create it.

在JDBC驱动中,有一块静态代码,也叫静态初始化块,它执行的时间是当class调入到内存中就执行(你可以想像成,当类调用到内存后就执行一个方法)。所以很多人把jdbc driver调入到内存中,再实例化对象是没有意义的。

 我们知道在Java中一切都是对象,我们一般所使用的对象都直接或间接继承自Object类。Object类中包含一个方法名叫getClass,利用这个方法就可以获得一个实例的类型类。类型类指的是代表一个类型的类,因为一切皆是对象,类型也不例外,在Java使用类型类来表示一个类型。所有的类型类都是Class类的实例。例如,有如下一段代码:

A a = new A();

if(a.getClass()==A.class)

System.out.println("equal");

else System.out.println("unequal");

结果就是打印出 “equal”。

    可以看到,对象a是A的一个实例,A某一个类,在if语句中使用a.getClass()返回的结果正是A的类型类,在Java中表示一个特定类型的类型类可以用“类型.class”的方式获得,因为a.getClass()获得是A的类型类,也就是A.class,因此上面的代码执行的结果就是打印出 “equal”。特别注意的是,类型类是一一对应的,父类的类型类和子类的类型类是不同的,因此,假设A是B的子类,那么如下的代码将得到 “unequal”的输出:

A a = new A();

if(a.getClass()==B.class)

System.out.println("equal");

else System.out.println("unequal");

因此,如果你知道一个实例,那么你可以通过实例的“getClass()”方法获得该对象的类型类,如果你知道一个类型,那么你可以使用“.class”的方法获得该类型的类型类。

2,获得类型的信息

在获得类型类之后,你就可以调用其中的一些方法获得类型的信息了,主要的方法有:

getName():String:获得该类型的全称名称。

getSuperClass():Class:获得该类型的直接父类,如果该类型没有直接父类,那么返回null。

getInterfaces():Class[]:获得该类型实现的所有接口。

isArray():boolean:判断该类型是否是数组。

isEnum():boolean:判断该类型是否是枚举类型。

isInterface():boolean:判断该类型是否是接口。

isPrimitive():boolean:判断该类型是否是基本类型,即是否是int,boolean,double等等。

isAssignableFrom(Class cls):boolean:判断这个类型是否是类型cls的父(祖先)类或父(祖先)接口。

getComponentType():Class:如果该类型是一个数组,那么返回该数组的组件类型。

此外还可以进行类型转换这类的操作,主要方法有:

asSubclass(Class clazz):Class:将这个类型


0 0