基本概念
元数据(mate data): 描述数据的描述数据
反射:得到类的原数据的过程(
在运行时期,动态地去获取某一个类中的成员信息(例如:构造器,方法,字段,内部类,接口,父类等等)
)
获取字节码对象
方式一:使用class属性
Class<java.util.Date> clz = java.util.Date.class;
方式二:通过对象的getClass方法获取,getClass是Object类中的方法
java.util.Date data=new java.util.Date();
Class<?> clz1 = data.getClass();//要有具体的对象才可以使用getClass()方法
方式三:通过Class类中的静态方法forName(String className);
Class<?>clz2=Class.forName("java.util.Date");
以上单个对象均是同一个对象,原因是同一个类在JVM中只存在一份字节码对象,也是就是说上述 clzclz1clz2
使用对多是第三种方式,在框架中大量使用
注意
基本数据类型不能表示为对象,也就不能使用getClass的方式,基本类型没有类名的概念,也不能使用Class.forName的方式
所有的数据类型都有class属性
Class clz = 数据类型.class
九大内置Class实例:JVM中预先提供好的Class实例,分别是byte,short,int,long,float,double,char,blean,void
byte.class,short.class,int.class,long.class,float.class,double.class,char.class,blean.class,void.class
//八大基本数据类型Class实例
System.out.println(byte.class);
System.out.println(short.class);
System.out.println(int.class);
System.out.println(long.class);
System.out.println(float.class);
System.out.println(double.class);
System.out.println(char.class);
System.out.println(boolean.class);
System.out.println(void.class);
在八大基本数据类型的包装类中,都有一个常量Type:用于返回该包装类的字节码对象
System.out.println(Integer.TYPE == int.class);//true
数组的Class实例:
数组是引用数据类型,数组其实是对象
数组中class实例的表示:
方式一:数组类型.class;
方式二:数组对象.getClass();
注意:所有的具有相同的维数和相同元素类型的数组共享同一份字节码对象,和元素没有关系
class:描述所有的类型,所以class类中应该具有类型中相同的方法
Object:描述所有的对象,所以在Object类中应该具有所有对象的共同的方法
通过反射来获取来获取某一个类的构造器
1、获取该类的字节码对象
2、从该字节码对象中去找需要获取的构造器
public class GetConstractor {
public static void main(String[] args) throws Exception {
// getAll();
getOne();
}
//获取所有的构造器
public static void getAll(){
//1、获取构造器所在类的字节码对象
Class<User> clz1 = User.class;
//2、获取clz对象中所有的构造器
Constructor<?>[] cs = clz1.getConstructors();
System.out.println(cs.length);
for (Constructor<?> c:cs
) {
System.out.println(c);
}
System.out.println("-------------");
cs=clz1.getDeclaredConstructors();
System.out.println(cs.length);
for (Constructor<?> c:cs
) {
System.out.println(c);
}
}
//获取指定的一个构造方法
public static void getOne() throws Exception {
Class<User> clz1 = User.class;
//获取public User() 构造器
Constructor<User> constructor = clz1.getConstructor();
System.out.println(constructor);
//获取 public User(String name)构造方法
constructor=clz1.getConstructor(String.class);
System.out.println(constructor);
//获取private User(String name,int age)构造方法
constructor=clz1.getDeclaredConstructor(String.class,int.class);
System.out.println(constructor);
}
}
使用反射创建对象
1、找到构造器所在类的字节码对象
2、获取构造器
3、使用反射,创建对象
package cn.blogsx.demo;
import com.sun.org.apache.bcel.internal.generic.NEW;
import java.lang.reflect.Constructor;
class Persion{
public Persion() {
System.out.println("无参构造方法");
}
public Persion(String name){
System.out.println("构造器"+name);
}
private Persion(String name,int age){
System.out.println("构造器"+name+","+age);
}
}
public class CreateObject {
public static void main(String[] args) throws Exception {
//传统构造方法
// new Persion();
System.out.println("===========");
//获取字节码对象
Class<Persion> clz = Persion.class;
//获取构造方法
Constructor<Persion> con = clz.getDeclaredConstructor(String.class,int.class);
//调用构造器的newInstance方法来创建对象,并传入参数
con.setAccessible(true);
Persion p = con.newInstance("hello",20);
System.out.println(p);
}
}
使用反射获取类中的方法:
1、获取方法所在类的字节码对象
2、获取方法
使用反射调用静态方法
静态方法不属于任何对象,静态方法属于类本身,此时把invoke方法的第一个参数省去