1. 三种获取类对象的方式
三种获取类对象的方式,内存中一个类只会有一个class对象。
public static void main(String[] args) throws ClassNotFoundException {
//通过反射来获取对象的方式,包名+类名
//内存中一个类只会有一个class对象
Class s1 = Class.forName("study.TestSort");
Class s2 = TestSort.class;
TestSort testSort = new TestSort();
Class s3 = testSort.getClass();
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
}
2.哪些类有Class 对象?
- class
- 接口
- []数组
- enum 枚举
- annotation 注解
- 基本数据类型
- void
3. 类的执行顺序:
首先是类的内容:静态变量、静态初始化块
再是 实例内容:变量、初始化块、构造器
4.什么时候会发生类的初始化?
类分为主动引用和被动引用。主动引用会发生类的初始化,被动引用不会。
被动引用
//引用类的常量不会发生初始化,常量通常在链接阶段就存入调用类的常量池中了
public class ReflectTest {
static {
System.out.println("Main类被加载");
}
public static void main(String[] args) {
System.out.println(Son.M);
}
}
class Father{
static int b = 2;
static {
System.out.println("父类被加载");
}
}
class Son extends Father{
static {
System.out.println("子类被加载");
m = 300;
}
static int m = 100;
static final int M = 1;
}
输出
Main类被加载
1
M被final修饰,不需要去初始化,在链接阶段就存在了。
需要初始化的时候:
当虚拟机启动,会先初始化main方法所在的类。
当new一个对象时。
调用类的静态成员(除了final)和静态方法也会初始化。
对类进行反射调用。
public static void main(String[] args) {
System.out.println(Son.m);
}
前面例子里,打印这个
输出
Main类被加载
父类被加载
子类被加载
100
5.通过反射获取类的参数
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c1 = User.class;
//调用无参构造函数
//User user = (User) c1.newInstance();
//用构造器创建对象
Constructor constructor = c1.getDeclaredConstructor();
User user = (User) constructor.newInstance();
//获取setName方法,如果setname方法是private,是无法invoke的,必须要setAccessible(true)
Method setNameMethod = c1.getDeclaredMethod("setName", String.class);
setNameMethod.setAccessible(true);
setNameMethod.invoke(user,"mmm");
System.out.println(user.getName());
}
对象关系映射
ORM 对象和表结构对象
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class s1 = Class.forName("reflect.Student");
//通过反射获得value的值
Table table = (Table) s1.getAnnotation(Table.class);
String value = table.value();
System.out.println(value);
java.lang.reflect.Field field = s1.getDeclaredField("name");
Field fieldAnnotation = field.getAnnotation(Field.class);
System.out.println(fieldAnnotation.columnName());
}
}
@Table("db_student")
class Student{
@Field(columnName = "name", type = "varchar")
private String name;
@Field(columnName = "type", type = "int")
private int age;
}
//放在class上
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field{
String columnName();
String type();
}