一个对象的创建发生了什么?
首先 虚拟机会先去检查 这个类是否已经被载入到内存,这里的类被载入指的类加载器是否已经载入过类的字节码(类的加载只会发生一次),字节码也就是你编写的.java文件 经编译之后生成的 .class文件。 (Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部都是程序运行的必要数据。) 虚拟机根据这个 字节码描述的具体信息 创建了这个类的实例。 --关于Class文件具体信息 可以参考Class文件
什么是反射?
java可以在运行时动态获取某个类的类信息,这就是java的反射。那么这个类的类信息怎么获得呢,这就说到Class类了,Class 类是为了描述一个类的信息,这里说的信息包括 这个类的 成员变量,构造函数,方法等信息, 而且Java为 这些信息 也抽象出了类,比如 描述 方法的类 Method 类, 构造函数的类 Constructor 类。 所以得到了一个 得到了一个类 的Class 类对象,也就得到了一个类的所有信息。
如何获得某一个类的信息,也就是如何获得这个类的字节码文件对象?
java中有三种方式可以获得
package up9527.com;
public class Person{
private int id;
Person(){
}
public int getId(){
return this.id;
}
public void setId(int id){
this.id = id;
}
public static void main(String[] args) throws ClassNotFoundException {
Person p = new Person();
//根据一个类的实例获得
Class pclazz = p.getClass();
System.out.println(pclazz.getName());
//根据一个Class类的forName()方法获得 参数时这个类的权限定名称,也就是要带上具体的包名
Class pclazz1 = Class.forName("up9527.com.Person");
System.out.println(pclazz.getName());
//通过类名.class获得
Class pclazz2 = Person.class;
System.out.println(pclazz.getName());
}
}
一般常用的方法 是第二种,也就是通过一个类的全权限定名称来创建一个类的实例,或者其他用途, 许多框架都会用到这个反射方法。 使用类的反射提高了程序的 可伸缩,可重用 ,可拓展。
假设 Student 类,Teacher类继承与 Person类,我们可以这样写,这里的forName()方法中的字符串 从.xml ..等等文本 配置文件读取,这样如果想创建不同的实例,只需要更改 权限定名称字符串(配置文件)就可以了。
Class clazz1 = Class.forName("up9527.com.Student");
Person p1 = (Person) clazz1.newInstance();
Class clazz2 = Class.forName("up9527.com.Teacher");
Person p2 = (Person) clazz2.newInstance();
newInstance getConstrot getDeclaredConstructor 方法的区别
1. newInstance 只能获得无参构造函数
2. Constructor<T> getConstructor(Class<?>... parameterTypes)根据传入的参数,获得 非私有的构造函数
根据传入的参数 ,可以获得私有的构造函数3.public Constructor<?> getDeclaredConstructors
其他的方法都大同小异
方法摘要 | ||
---|---|---|
| asSubclass(Class<U> clazz) 强制转换该 Class 对象,以表示指定的 class 对象所表示的类的一个子类。 | |
T | cast(Object obj) 将一个对象强制转换成此 Class 对象所表示的类或接口。 | |
boolean | desiredAssertionStatus() 如果要在调用此方法时将要初始化该类,则返回将分配给该类的断言状态。 | |
static Class<?> | forName(String className) 返回与带有给定字符串名的类或接口相关联的 Class 对象。 | |
static Class<?> | forName(String name, boolean initialize,ClassLoader loader) 使用给定的类加载器,返回与带有给定字符串名的类或接口相关联的 Class 对象。 | |
| getAnnotation(Class<A> annotationClass) 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。 | |
Annotation[] | getAnnotations() 返回此元素上存在的所有注释。 | |
String | getCanonicalName() 返回 Java Language Specification 中所定义的底层类的规范化名称。 | |
Class<?>[] | getClasses() 返回一个包含某些 Class 对象的数组,这些对象表示属于此 Class 对象所表示的类的成员的所有公共类和接口。 | |
ClassLoader | getClassLoader() 返回该类的类加载器。 | |
Class<?> | getComponentType() 返回表示数组组件类型的 Class 。 | |
Constructor<T> | getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 | |
Constructor<?>[] | getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。 | |
Annotation[] | getDeclaredAnnotations() 返回直接存在于此元素上的所有注释。 | |
Class<?>[] | getDeclaredClasses() 返回 Class 对象的一个数组,这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口。 | |
Constructor<T> | getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 | |
Constructor<?>[] | getDeclaredConstructors() 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。 | |
Field | getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 | |
Field[] | getDeclaredFields() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。 | |
Method | getDeclaredMethod(String name,Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 | |
Method[] | getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 | |
Class<?> | getDeclaringClass() 如果此 Class 对象所表示的类或接口是另一个类的成员,则返回的 Class 对象表示该对象的声明类。 | |
Class<?> | getEnclosingClass() 返回底层类的立即封闭类。 | |
Constructor<?> | getEnclosingConstructor() 如果该 Class 对象表示构造方法中的一个本地或匿名类,则返回 Constructor 对象,它表示底层类的立即封闭构造方法。 | |
Method | getEnclosingMethod() 如果此 Class 对象表示某一方法中的一个本地或匿名类,则返回 Method 对象,它表示底层类的立即封闭方法。 | |
T[] | getEnumConstants() 如果此 Class 对象不表示枚举类型,则返回枚举类的元素或 null。 | |
Field | getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 | |
Field[] | getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 | |
Type[] | getGenericInterfaces() 返回表示某些接口的 Type,这些接口由此对象所表示的类或接口直接实现。 | |
Type | getGenericSuperclass() 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type。 | |
Class<?>[] | getInterfaces() 确定此对象所表示的类或接口实现的接口。 | |
Method | getMethod(String name,Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 | |
Method[] | getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共member 方法。 | |
int | getModifiers() 返回此类或接口以整数编码的 Java 语言修饰符。 | |
String | getName() 以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。 | |
Package | getPackage() 获取此类的包。 | |
ProtectionDomain | getProtectionDomain() 返回该类的 ProtectionDomain 。 | |
URL | getResource(String name) 查找带有给定名称的资源。 | |
InputStream | getResourceAsStream(String name) 查找具有给定名称的资源。 | |
Object[] | getSigners() 获取此类的标记。 | |
String | getSimpleName() 返回源代码中给出的底层类的简称。 | |
Class<? superT> | getSuperclass() 返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class 。 | |
TypeVariable<Class<T>>[] | getTypeParameters() 按声明顺序返回 TypeVariable 对象的一个数组,这些对象表示用此 GenericDeclaration 对象所表示的常规声明来声明的类型变量。 | |
boolean | isAnnotation() 如果此 Class 对象表示一个注释类型则返回 true。 | |
boolean | isAnnotationPresent(Class<? extendsAnnotation> annotationClass) 如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。 | |
boolean | isAnonymousClass() 当且仅当底层类是匿名类时返回 true。 | |
boolean | isArray() 判定此 Class 对象是否表示一个数组类。 | |
boolean | isAssignableFrom(Class<?> cls) 判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口。 | |
boolean | isEnum() 当且仅当该类声明为源代码中的枚举时返回 true。 | |
boolean | isInstance(Object obj) 判定指定的 Object 是否与此 Class 所表示的对象赋值兼容。 | |
boolean | isInterface() 判定指定的 Class 对象是否表示一个接口类型。 | |
boolean | isLocalClass() 当且仅当底层类是本地类时返回 true。 | |
boolean | isMemberClass() 当且仅当底层类是成员类时返回 true。 | |
boolean | isPrimitive() 判定指定的 Class 对象是否表示一个基本类型。 | |
boolean | isSynthetic() 如果此类是复合类,则返回 true,否则 false。 | |
T | newInstance() 创建此 Class 对象所表示的类的一个新实例。 | |
String | toString() 将对象转换为字符串。 |
下面给出,一个获得类的构造函数,以及调用这个 构造函数类的 方法创建实例的例子
package up9527.com;
import java.lang.reflect.Constructor;
import org.omg.Messaging.SyncScopeHelper;
public class Person{
private int id;
Person(){
}
private Person(int id){
this.id = id;
}
public int getId(){
return this.id;
}
public void setId(int id){
this.id = id;
}
public void print(){
System.out.println("我的Id 是"+id);
}
public static void main(String[] args) throws Exception {
//根据一个Class类的forName()方法获得 参数时这个类的权限定名称,也就是要带上具体的包名
Class clazz = Class.forName("up9527.com.Person");
//通过反射来的 Person类的 Class类型的实例 创建一个 Person类的实例
//Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数;
Person p = (Person) clazz.newInstance();
p.print();
//getDeclaredConstructor方法可以得到私有的构造函数,还有个getConstructor 这个不能得到私有的构造函数
Constructor<Person> pc = clazz.getDeclaredConstructor(int.class);
Person p1 =pc.newInstance(2);
p1.print();
}
}