Copyright©Stonee
在Java中,无论是类还是接口,它们在JVM的内存逻辑模型中都会存在Super和Class指针,分别指向根类(Object类)和反射类(Class类)
在这一篇blog中会了解到很多常用方法,建议大家看api
public class java.lang.Object
{
public java.lang.Object();
protected void finalize();
public final native void wait(long);
public final void wait(long, int);
public final void wait();
public boolean equals(java.lang.Object);
public java.lang.String toString();
public native int hashCode();
public final native java.lang.Class getClass();
protected native java.lang.Object clone();
public final native void notify();
public final native void notifyAll();
private static native void registerNatives();
}
关于class的就不再详细列出
Object类是每个类的始祖,Java中的任何一个类都是由Object类扩展而来,但不用写
class a extends Object
,无论是否指出,Object都被认为是此类的直接超类或间接超类。所以任何类都可以调用Object类中方法
Object obj = new A();
A a = (A) obj;
但是需要注意,这种向下转型极有可能出错:如下
Object obj = new A();
A aa = (A) obj; //正确
Object obj = new B();
A ab = (A) obj; //错误
相信大家可以看到,向下转型的条件必须是父类指向转型类的实例
在平时编写子类的时候,经常要重写Object中的几个方法,如下:
public boolean equals(Object obj)
底层的实现过程为:
public boolean equals(Object obj) {
return (this == obj);
}
检测两个对象是否具有相通的引用,其中“==”比较的是地址值。下面是一个重写的例子:
class a {
private int a;
public a( int a){
this.a = a;
}
public boolean equals(a obj){
return this.a == obj.a;
}
}
public native int hashCode();
在Java应用程序执行期间,无论何时在同一个对象上多次调用它,hashCode方法都必须始终返回相同的整数,前提是不修改对象上等号比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,此整数不必保持一致。
如果根据equals(Object)方法,两个对象是相等的,那么在每个对象上调用hashCode方法必须产生相同的整数结果。
但是并没有强制要求如果equals()判断两个对象不相等,那么它们的hashCode()方法就应该返回不同的值。
public String toString()
底层实现为:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
Object中的toString返回的是:包名+类名+@+对象hashCode的16进制。所以当我们需要将派生类中进行字符串转换时,也需要重写toString方法
public final native Class> getClass();
取得该类已经被实例化了的对象的该类的引用,这个引用指向的是Class类的对象
Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,即所谓的RTTI。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
假设
a
为一个类对象,则获得a的类对象:
Class c = a.getClass()
Class c = Class.forName(a)
但是由于传入的a可能不是类实例,所以此处应提供一个异常处理器,否则会抛出checkedexception异常Class c = int.class;
注意,int需要先自动装箱,使用这种办法生成Class类对象时,不会使JVM自动加载该类(如Integer类)。而其他办法会使得JVM初始化该类。 Class c = Class.forName(a);
Object aInstance=obj.newInstance();
package chapter05;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;
/**
* This program uses reflection to print all features of a class
* @version 1.0 2019-04-7
* @author stonee(http://www.stonee.club)
*/
public class ReflectionTest {
public static void main(String [] args){
//read class name from command line args or user input
int flag = 1;
String name; //class name
Scanner input = new Scanner(System.in);
while(flag == 1){
if (args.length > 0) //from command line args
name = args[0];
else{ //from user input
System.out.println("Enter class name (e.g. java.util.Date) : ");
name = input.next();
}
try {
//print class name and superClass name
Class c1 = Class.forName(name); //get class
Class superC1 = c1.getSuperclass(); //get superClass
String modifiers = Modifier.toString(c1.getModifiers()); //get the "public" to string
if (modifiers.length() > 0)
System.out.print(modifiers + " "); //print the "public"
System.out.print("class " + name); //print the class name
if (superC1 != null && superC1 != Object.class)
System.out.print(" extends " + superC1.getName()); //print the superClass if have
System.out.print("\n{\n"); //print "{"
printConstructors(c1);
System.out.println();
printMethods(c1);
System.out.println();
printField(c1);
System.out.println("}");
}
catch (ClassNotFoundException e){
e.printStackTrace();
}
//System.exit(0);
System.out.println("Do you wanna go on this program ?(1 or 0)");
flag = input.nextInt();
}
}
/**
* prints all constructors of a class
* @param c1 a class
*/
private static void printConstructors(Class c1){
Constructor [] constructors = c1.getDeclaredConstructors(); //返回这个类或接口所有共有方法,不包括继承
for (Constructor c:
constructors) {
String name = c.getName();
System.out.print(" ");
String modifiers = Modifier.toString(c.getModifiers()); //get the "public" to string
if (modifiers.length() > 0)
System.out.print(modifiers + " "); //print the "public"
System.out.print(name + "(");
// print parameter types
Class [] paramTypes = c.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++){
if (i > 0)
System.out.print(", ");
System.out.print(paramTypes[i].getName());
}
System.out.println(");");
}
}
private static void printMethods(Class c1){
Method[] methods = c1.getDeclaredMethods();
for (Method m:
methods) {
Class retType = m.getReturnType(); //得到返回值
String name = m.getName();
System.out.print(" ");
//print modifiers, return type and method name
String modifiers = Modifier.toString(m.getModifiers()); //get the "public" to string
if (modifiers.length() > 0)
System.out.print(modifiers + " "); //print the "public"
System.out.print(retType.getName() + " " + name + "("); //打印方法的返回值和方法名
//print the parameter types
Class [] paramTypes = m.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++){
if (i > 0)
System.out.print(", ");
System.out.print(paramTypes[i].getName());
}
System.out.println(");");
}
}
private static void printField(Class c1) {
Field[] fields = c1.getDeclaredFields();
for (Field f :
fields) {
Class fType = f.getType(); //得到返回值
String name = f.getName();
System.out.print(" ");
//print modifiers, return type and method name
String modifiers = Modifier.toString(f.getModifiers()); //get the "public" to string
if (modifiers.length() > 0)
System.out.print(modifiers + " "); //print the "public"
System.out.print(fType.getName() + " " + name + ";" ); //打印方法的返回值和方法名
System.out.println();
}
}
}