注解和反射
注解Annotation
不是程序本身,但是可以对程序进行解释
格式: @注释名
内置注解:
@Override 重写超类
@Deprecated 已废弃的 不推荐使用(仍然可以用)
@SuppressWarnings 镇压警告(必须传参数才能使用)
元注解:
负责注解其他注解的注解
@Target ()表示注解可以用在哪些地方
@Retention 表示在什么地方还有效
@Documented 是否生成在JAVAdoc中
@Inherited 表示子类可以继承父类的注解
@MyAnnotation
public class Demo_01 {
}
@Target(value={ElementType.METHOD,ElementType.TYPE})//用在方法上 和类上
@Retention(value= RetentionPolicy.RUNTIME)//表示注解在什么地方还有效
@Documented //表示是否将我们的注解生成在JAVAdoc中
@Inherited //子类可以继承父类的注解
@interface MyAnnotation{
}
自定义注解
@interface MyAnnotation{
//注解的参数: 参数类型 +参数名()
String name() default"";
int age() default 0;
int id() default -1;//默认值为-1代表不存在
String[] schools() default{"你好","自定义"}
}
反射 Reflection
反射是Java被视为动态语言的关键,反射机制允许程序在执行期间借助Reflection 取得任何类的内部信息,并且能直接操作任意对象的内部属性及方法
优点:动态创建对象和编译,体现出很大的灵活性
缺点:影响性能
Class类的获取
public class Demo_03 {
public static void main(String[] args) throws ClassNotFoundException {
Person person=new Student();
//方式1:通过对象获取
Class c1=person.getClass();
System.out.println(c1.hashCode());
//方式2:forName获取
Class c2=Class.forName("day_04.Student");
System.out.println(c2.hashCode());
//方式3:通过类名。class获取
Class c3=Student.class;
System.out.println(c3.hashCode());
//方法4:基本内置类型和包装类都有一个Type属性
Class<Integer> c4=Integer.TYPE;
System.out.println(c4.hashCode());
//获取父类类型
Class c5= c1.getSuperclass();
}
}
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Student extends Person{
public Student(){
this.name="学生" ;
}
}
class Teacher extends Person{
public Teacher(){
this.name="老师" ;
}
}
所有类型的Class类
import java.lang.annotation.ElementType;
public class Demo_04 {
public static void main(String[] args) {
Class c1=Object.class;//类
Class c2=Comparable.class;//接口
Class c3=String[].class;//一维数组
Class c4=int[][].class;//二维数组
Class c5=Override.class;//注解
Class c6= ElementType.class;//枚举
Class c7=Integer.class;//基本数据类型
Class c8=void.class;//void
Class c9=Class.class;//Class本身
System.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);
System.out.println(c9);
//只要元素类型与维度一直,就是一个Class
int[]a=new int[10];
int[]b=new int[100];
System.out.println(a.getClass().hashCode());
System.out.println(b.getClass().hashCode());
}
}
类加载内存分析
了解类的加载过程:
类的加载Load-------> 类的链接Link--------->类的初始化Initialize
加载:将class文件字节码内容加载到内存中,并将这些静态数据转化成方法区的运行时数据结构,然后生成一个代表这个类的 java.lang.Class对象
链接:将java类的二进制代码合并到JVM运行状态中的过程
- 验证:确保加载的类信息符合JVM规范
- 准备:正式为类变量(static)分配内存并设置类变量默认初始值,这些内存都将在方法区中进行分配
- 解析:虚拟机常量池内的符号引用代替为直接引用的过程
初始化
- 执行类构造器()方法的过程,类构造器是构造类信息的,不是构造类对象的
- 当初始化一个类时,如果父类没有被初始化,则先出发父类的初始化
- 虚拟机会保证一个类的client方法在多线程环境中被正确的加锁和同步
类的加载过程
public class Demo_05 {
public static void main(String[] args) {
A a=new A();
System.out.println(A.m);
}
/**
* 1,加载到内存,产生一个类对应的class对象
* 2,链接,链接后m=0
* 3,初始化System.out.println("A类的静态代码初始化");
* m=300;
* m=100;
* ---->m=100
*
*/
}
class A{
static {
System.out.println("A类的静态代码初始化");
m=300;
}
static int m=100;
public A(){
System.out.println("A的无参构造初始化");
}
}
什么时候会发生类的初始化
获取类运行时的完整结构
public class Test_02 {
//获取类的信息
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1=Class.forName("day_04.User");
//类名:
System.out.println(c1.getName());
System.out.println(c1.getSimpleName());
//类的属性
Field[] fields= c1.getFields();
for (Field field : fields) {
System.out.println(field);
}
//获取指定属性的值
Field name=c1.getDeclaredField("name");
System.out.println(name);
//获取类的方法
System.out.println("==============================");
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println("正常的"+method);
}
methods=c1.getDeclaredMethods();//获取本类的所有方法
for (Method method : methods) {
System.out.println("getDecleredMethods:"+method);
}
//获取指定的方法
Method getName = c1.getMethod("getName", null);
Method setName = c1.getMethod("setName", String.class);
//获得指定的构造器
System.out.println("===========================");
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
Constructor[] declaredConstructors = c1.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
}
}
动态创建对象执行方法
public class Demo_07 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Class c1=Class.forName("day_04.User");
//构造一个对象
User user =(User) c1.newInstance();//本质是是调用了类的无参构造器
System.out.println(user);
System.out.println("==================");
//通过构造器创建方法
Constructor constructor=c1.getDeclaredConstructor(String.class,int.class,int.class);
User user1=(User)constructor.newInstance("麒",001,18);
System.out.println(user1);
System.out.println("====================");
//通过反射获取一个方法
User user2=(User)c1.newInstance();
Method setName=c1.getDeclaredMethod("setName", String.class);
setName.invoke(user2,"麒0");//invork (对象,方法的值)
System.out.println(user2.getName());
System.out.println("======================");
//通过反射操作属性
User user3=(User) c1.newInstance();
Field name= c1.getDeclaredField("name");
//关闭权限检测 不能直接操作私有属性,需要关闭
name.setAccessible(true);
name.set(user3,"麒1");
System.out.println(user3);
}
}
性能对比分析
public class Demo_08 {
public static void test01(){
User user=new User();
long startTime=System.currentTimeMillis();
for(int i=0;i<=1_000_000_000;i++){
user.getName();
}
long endTime=System.currentTimeMillis();
System.out.println("普通方法执行10亿次:"+(endTime-startTime)+"ms");
}
public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user =new User();
Class c1=user.getClass();
Method getName = c1.getDeclaredMethod("getName", null);
long startTime=System.currentTimeMillis();
for(int i=0;i<=1_000_000_000;i++){
getName.invoke(user,null);
}
long endTime=System.currentTimeMillis();
System.out.println("反射方法执行10亿次:"+(endTime-startTime)+"ms");
}
public static void test03() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
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<=1_000_000_000;i++){
getName.invoke(user,null);
}
long endTime=System.currentTimeMillis();
System.out.println("关闭检测反射方法执行10亿次:"+(endTime-startTime)+"ms");
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
test01();
test02();
test03();
}
}
通过反射操作注解
ORM:对象关系映射 Object Relation Mapping
public class Demo_10 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("day_04.Student2");
//通过发射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获取注解value值
Table_phq table_phq=(Table_phq)c1.getAnnotation(Table_phq.class);
String value=table_phq.value();
System.out.println(value);
//获取类指定的注解
Field f=c1.getDeclaredField("name");
Field_phq annotation = f.getAnnotation(Field_phq.class);
System.out.println(annotation.columnName());
System.out.println(annotation.length());
System.out.println(annotation.type());
}
}
@Table_phq("db_student")
class Student2{
@Field_phq(columnName = "db_id",type="int",length = 10)
private int id;
@Field_phq(columnName = "db_age",type="int",length = 10)
private int age;
@Field_phq(columnName = "db_name",type="String",length = 10)
private String name;
public Student2(int id, int age, String name) {
this.id = id;
this.age = age;
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;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student2() {
}
@Override
public String toString() {
return "Student2{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table_phq{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field_phq{
String columnName();
String type();
int length();
}