1. 自定义注解@interface
@interface MyAnno {
//注解类型:参数类型参数名()defult默认值;
String name() default "";
int age() default 0;
int id() default -1;
String[] schools();
//无默认值,那外部写这个注解时就必须带参数!}
//测试类
public class Test {
@MyAnno(name = "jiaxin")
public void test () {
....
}
}
【注解与反射_1 - 小记】2.元注解
//表示我们的注解可以用在哪些地方
@Target(value = https://www.it610.com/article/{ElementType.METHOD , ElementType.ANNOTATION_TYPE})//表示我们的注解在什么地方还有效runtime> class > sources
@Retention(value = https://www.it610.com/article/RetentionPolicy.RUNTIME)//表示是否将我们的注解生成在java doc中
@Documented//子类可以继承父类的注解
@Inherited
@interface MyAnno {}
3.注解种类:
内置注解+元注解+自定义注解
反射Reflection
1.反射机制是Java被视为动态语言的关键,在框架Spring、Mybatis代码中有所体现。
2.如何创建对象? new或者clone()克隆或者反射!!
3.反射与注解相结合。 反射可以获取类的内部信息,动态化(运行时刻可以查看、改变其结构的)。
4.比较:
正常方式:引入包类名-new-获取实例化对象
反射方式:实例化对象-getClass()-得到完整的包类名称
5.反射机制提供的功能:
判断任一对象所属的类
构造任一类的对象
判断任一类所具有的属性和方法
获取泛型信息
处理注解
调用任一个对象的成员变量及方法
生成动态代理
....
6.优缺点:
优:实现动态创建对象和编译+灵活性
缺:影响性能
package com.tencent.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
public class Test8 {public static void t1() {
User user = new User();
long startTime = System.currentTimeMillis();
for(int i = 0;
i < 1000000000 ;
i++) {
user.getName();
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime + "ms");
//5-6ms
}public static void t2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName" , null);
getName.setAccessible(false);
long startTime = System.currentTimeMillis();
for(int i = 0;
i < 1000000000 ;
i++) {
getName.invoke(user , null);
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime + "ms");
//5-6ms
}public static void t3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user = new User();
Class c1 = user.getClass();
Method getName = c1.getDeclaredMethod("getName" , null);
getName.setAccessible(true);
long startTime = System.currentTimeMillis();
for(int i = 0;
i < 1000000000 ;
i++) {
getName.invoke(user , null);
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime + "ms");
//5-6ms
}public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
System.out.print("普通调用getName():");
Test8.t1();
System.out.print("开启安全检测,调用getName():");
Test8.t2();
System.out.print("关闭安全检测,调用getName():");
Test8.t3();
/*
普通调用getName():6ms
开启安全检测,调用getName():1917ms
关闭安全检测,调用getName():1295ms---说明反射消耗性能,费时.
* */
}
}
7.获取Class类的几种方法
package com.tencent.reflection;
public class Test2 {public static void main(String[] args) throws ClassNotFoundException {//1.通过对象 调用getClass()获取
User user = new User("jx" , 21);
Class c1 = user.getClass();
System.out.println(c1.hashCode());
//2.通过类的class属性获取
Class c2 = User.class;
System.out.println(c2.hashCode());
//3.通过类路径获取 forName()
Class c3 = Class.forName("com.tencent.reflection.User");
System.out.println(c3.hashCode());
//4.内置基本数据类型 包装类
Class c4 = Integer.TYPE;
System.out.println(c4);
//int//5.获得对象所属类的父类类型
System.out.println(c1.getSuperclass());
}
}
8.哪些类型具有Class对象(or 属性)?
package com.tencent.reflection;
import sun.reflect.generics.scope.ClassScope;
import java.lang.annotation.ElementType;
public class Test3 {public static void main(String[] args) {Class c1 = Object.class;
//类Class c2 = Comparable.class;
//接口Class c3 = String[].class;
//数组Class c4 = Override.class;
//注解Class c5 = ElementType.class;
//枚举Class c6 = Integer.class;
//基本数据类型Class c7 = void.class;
//voidClass c8 = Class.class;
//ClassSystem.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
//元素类型相同,则获取对应的Class类型都相同
int[] a = new int[10];
//1163157884
int[] b = new int[100];
//1163157884
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
}
}
9.Java内存分析
栈:存放基本数据类型+引用对象的变量地址
堆:存放对象+数组,可被所有线程共享,注:存放Class对象!
方法区:被所有线程共享,存放 static静态变量
10.类加载过程
分三步
类加载Load + 类链接Link + 类初始化Initialize
a.加载: class文件字节码,加载到内存中,将静态数据转换成方法区的运行时数据结构,在堆中生成Class对象
b.链接:
验证:检查类信息符合JVM规范,有无安全问题;
准备:为类变量,即:静态变量,分配内存,设置默认初始值;
解析:虚拟机常量池,符号引用 替换为 直接引用地址 的过程。
c.初始化:
执行类构造器clinit()的过程;
初始化一个类,要检查其父类,先初始化父类;
虚拟区要确保一个类的构造器clinit()在多线程环境下,加锁及同步的进行。
11.什么情况发生类的初始化?
主动引用会发生;被动引用不会。
主动引用:略;
引言:主动引用中,当前程序执行的Main方法一定会初始化。被动引用:
a. 访问静态域的话,是真正声明这个域的类才会初始化!例如:
通过子类引用父类的静态变量,则不会引起子类的初始化!只会引起父类的初始化。b. 通过数组定义类访问时,不会加载当前定义类的初始化!c. 引用常量。不会引起当前定义类的初始化!
因为常量在链接的第三步解析步骤下,就会调入常量池中了。
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- jvm|【JVM】JVM08(java内存模型解析[JMM])
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)