引言
事实上,学到后面框架你会发现到处都是注解开发因为省时省力,反射也无处不在,所以大家爱用框架。
注解是JDK5.0开始引入的计数
重点: 可以被其它程序读取
内置注解
@override 重写方法是指内容的重写
//重载是指在方法变量个数,变量类型,变量名
@Deprecated 不鼓励程序员选择,废弃
@SuppressWarnings("all") 镇压警告unchecked等
元注解
负责注解其它注解,
@Target(value={ElemrntType.METHOD等})
public @interface sd{ //自定义一个注解,目标在哪个地方可以作用
String name(); //注解的参数: 参数的类型+参数名();注解了就必须要参数除非是 //String name() default "";
}
@Retention(value=RetentionPolicy.RUNTIME) 用于描述注解的生命周期(source<class<runtime)注解在什么地方有效
@Documented 用于文档注释
@Inherited 子类可以继承父类中该注解
反射概述(重点)
在程序运行的时候通过反射可以加进去(Hook)
Class c=Class.forName(“java.lang.String”)
每个类都有个Class对象
优点:
可以动态创建对象和编译,灵活性大
缺点:
对性能有影响,反射是解释性操作告诉JVM让他满足我们的要求
//创建class类
Class c1=person.getClass();
Class c2=Class.forName("java.lang.String")
Class c3=Student.Class;
Class c4=Integer.TYPE; //基本内置类型的包装类
Class c5=c1.getsuperClass();
//什么叫反射
public class Reflect {
public static void main(String[] args) throws Exception {
// TODO 自动生成的方法存根
//通过对象反射获取类的Class对象
Class c1=Class.forName("reflect.User");
System.out.println(c1);
Class c2=Class.forName("reflect.User");
Class c3=Class.forName("reflect.User");
Class c4=Class.forName("reflect.User");
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
System.out.println(c4.hashCode());
/* 输出:
class reflect.User
1112280004 hashcode说明一个类只加载一个类对象
1112280004 一个类被加载后类的结构都会被封装在class对象中
1112280004*/
}
}
class User{
private String name;
private int id;
private int age;
public User(String name, int id, int age) {
super();
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;
}
}
JAVA内存分析
new对象和数组,堆
基本变量类型和数值,还有引用的对象变量, 栈
包含了所有的class和static变量,方法区
类的加载与ClassLoader的理解
加载 将class的字节码文件加载到内存呢,并且静态数据转换成方法区数据结构,
链接 先分配空间初始化变量,
初始化 执行clinit方法,合并静态代码块并运行
然后主动引用的话比如new和反射会有类的初始化且优先加载main()方法
初始化一个类的时候其父类没有初始化,则优先初始化父类
然后被动引用的话比如只调用父类变量是不会让子类初始化的,
调用常量父类子类都不会引起初始化,因为在链接的时候常量就在常量池里了
动态创建对象
Class c1=Class.forName("java.lang.String")
User user=(User)c1.newInstance(); //本质调用了无参构造器
//调用了有参构造器创建对象
Constructor c=c1,getDeclaredConstructor(String.Class,int.Class);
User user=(User)C.newInstance("sad",1);
//通过反射调用普通方法
User user3=(User)c1.newInstance();
//通过反射获取一个方法
c1.getDeclaredMethod("setName",String.Class);
setName.invoke(user3,"sad"); //激活(对象,"方法值");
//反射获取字段的话需要关闭字段私有的权限检测setAccessible(true)关闭掉