什么时候会发生类初始化
获得加载器的方式 类.getClassLoader
获得加载器的路径
Mybatis,Spring 框架底层的部分
注解
类似于@Override重写
注解有检查和约束的作用,可以被其他程序访问,可以在package,class,method,field等上面,相当于添加了额外的辅助信息,可以通过反射机制编程实现对这些元数据的访问.
内置注解
加在想要操作的方法上面
@Override重写
@Deprecated 废弃,不推荐使用但是可以使用
@SuppressWarnings(“all”),镇压警告,不再显示警告,参数可以改变
元注解
负责解释其他注解的注解,定义注解
格式 public @interface 注解名{//如果在类的内部申请不带public
定义内容
}
public class test02 {
@MyAnnotation
public void test(){
}
}
//定义一个注解
// Target表示可以用在哪些地方
@Target(value ={ElementType.METHOD,ElementType.TYPE})
//Retention表示注解在什么地方有效,RunTime>class>source
@Retention(RetentionPolicy.RUNTIME)D
//Documented表示将注解是否生成到JAVAdoc中
@Documented
//Inherited写了表示子类可以继承父类的注解
@Inherited
//定义的注解
@interface MyAnnotation{
}
自定义注解
其中的每一个方法实际上是声明了一个配置参数.方法的名称就是参数的名称.
返回值类型就是参数的类型(返回值只能是基本类型,Class , String , enum ).可以通过default来声明参数的默认值
如果只有一个参数成员,一般参数名为value,
注解元素必须要有值﹐我们定义注解元素时,经常使用空字符串,0作为默认值.
String str();
int ID();
带default默认值的参数可以不写,但是不带default的参数必须写
String str() default "";
int ID() default 0;
反射
动态语言:在程序运行时能改变代码的内部结构并且能直接操作内部的属性 其中反射机制为Java被视为动态语言的关键
正常方式 导入包-> new 实例化->取得对象
反射方式 实例化对象->getclass()方法->得到完整的包类名称
反射机制提供的功能
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时获取泛型信息
在运行时调用任意一个对象的成员变量和方法
在运行时处理注解
生成动态代理
Class c1 = Class.forName("test.User");//写类名
Class c2 = Class.forName("test.User");
Class c3 = Class.forName("test.User");
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
//一个类只生成一个class文件,所以哈希值一样
得到class类的几种方式
-
.getSuperclass 获得父类class
-
直接对象名/类名.class
Class<User> userClass = User.class;
-
知道类的路径
Class c1 = Class.forName(“test.User”);//写类名
-
内置对象的包装类
Integer.TYPE
class内存分析
- 加载到内存,产生一个对应的classduixiang
- 链接,连接结束后属性会被赋一个默认值
- 初始化,加载代码
反射中获得对象,操作对象
Class<?> c1 = Class.forName("test.User");
User user = (User) c1.newInstance();//调用无参构造器,构造对象
//如果没有无参构造器,通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class,int.class);
User wpx = (User) constructor.newInstance("wpx", 20);//通过这个构造器传参
System.out.println(wpx);
//通过反射操作方法
User user2 = (User) c1.newInstance();
//通过反射获取方法
Method setname = c1.getDeclaredMethod("setName", String.class);
Method setid = c1.getDeclaredMethod("setID", int.class);
//invoke (对象,方法值)激活
setname.invoke(user2,"wpx");
setid.invoke(user2,22);
System.out.println(user2);
User{name='wpx', ID=22}
其他方法类似
//通过反射操作属性
User user3 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,需要关闭安全检测
name.setAccessible(true);
name.set(user3,"wpx");
System.out.println(user3.getName());
//其他属性类似
设置setAccessible(true); 提高反应效率
性能对比
public class ReflectionMin {
//普通方法
public static void test1(){
User user = new User();
long starTime = System.currentTimeMillis();//开始计时
for (int i = 0; i < 1000000000; i++) {
user.getName();
}
long endTime= System.currentTimeMillis();//结束计时
System.out.println("普通方法执行十亿次用时"+(endTime-starTime)+"ms");
}
//反射方法
public static void test2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c1 = Class.forName("test.User");
User user = (User) c1.newInstance();//通过反射方式创建对象,也可以直接new user
Method getName = c1.getDeclaredMethod("getName",null);//获取方法
long starTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user,null);//启动方法获得对象 ,因为get的构造器没有参数所以为空
}
long endTime= System.currentTimeMillis();
System.out.println("反射方法执行十亿次用时"+(endTime-starTime)+"ms");
}
//关闭安全检测
public static void test3() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c1 = Class.forName("test.User");
User user = (User) c1.newInstance();
Method getName = c1.getDeclaredMethod("getName",null);
getName.setAccessible(true);//关闭
long starTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(user,null);
}
long endTime= System.currentTimeMillis();
System.out.println("反射方法执行十亿次用时"+(endTime-starTime)+"ms");
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
test1();
test2();
test3();
}
}
运行结果
普通方法执行十亿次用时3ms
反射方法执行十亿次用时2371ms
反射方法执行十亿次用时1288ms
反射操作注解ORM
package test;
import java.lang.annotation.*;
public class test10 {
//反射操作注解
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class<?> c1 = Class.forName("test.student");
//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//通过反射获得注解的value值
table table = c1.getAnnotation(table.class);
String value = table.value();
System.out.println(value);
//获得类指定注解
java.lang.reflect.Field field = c1.getDeclaredField("name");
Field file = field.getAnnotation(Field.class);
System.out.println(file.Columnname());
System.out.println(file.type());
System.out.println(file.length());
}
}
//简单实体类
@table("db_student")
class student{
@Field(Columnname = "db_name",type ="varchar",length = 255)
private String name;
@Field(Columnname = "db_id",type ="int",length = 10)
private int id;
@Field(Columnname = "db_age",type ="int",length = 10)
private int age;
@Override
public String toString() {
return "student{" +
"name='" + name + '\'' +
", id=" + id +
", age=" + age +
'}';
}
public student() {
}
public student(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//自定义注解
//类的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface table{
String value();
}
/**
* @author 17699
*/ //属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field {
String Columnname();
String type();
int length();
}