元注解
负责注解其他注解(target )
@Target(value = {ElementType.METHOD,ElementType.TYPE})
//runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)
//表示是否生成在JAVAdoc中
@Documented()
//字类可以继承父类的注解
@Inherited
@interface MyAnnotation{
}
自定义注解
@interface MyAnnotation2 {
// 注解的参数:参数类型+参数名();
String name() default "";
int age() default 0;
int id() default -1;
String[] schools() default {"清华大学"};
}
反射
动态语言:运行时可以改变其结构(js)
反射允许类在运行期间获取类的任何内部信息(类名,接口,方法,属性)
Class c2 = Class.forName("com.fans.annotion_test");
Class c3 = Test.class;
Test2 t = new Test2();
Class c4 = t.getClass();
哪些类型可以有class对象
class,interface ,数组,枚举,注解,基本数据类型,void
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;
Class c9 = Class.class;
java内存分析
堆:存放new出来的对象和数组,可以被所有线程共享,不会存放别的对象引用
栈:存放基本变量类型(会包含这个基本类型的具体数值),引用对象的变量(会存放这个引用在堆里面的具体地址)
方法区(特殊的堆):可以被所有线程共享,包含了所有的static和class变量
类的加载
1.将类的class文件字节码内容读入内存,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的Class对象。
类的链接
2.将类的二进制文件合并到JRE中
类的初始化
jvm对类进行初始化
什么时候发生类的初始化
- new 一个类的对象
- 调用类的静态成员(除了final变量)和静态方法
- 反射调用
- 初始化一个类,父类没有初始化,就会初始化父类
不会产生类的初始化
- 引用父类的静态域
- 通过数组定义类引用
- 常量调用(链接阶段就被初始化)
类加载器
//系统加载器
ClassLoader system = ClassLoader.getSystemClassLoader();
// 扩展加载器
ClassLoader parent = system.getParent();
// 根加载器,jdk内置类
ClassLoader parent1 = parent.getParent();
// 如何获取系统加载器可以加载的路径
System.getProperty("java.class.path");
//双亲委派机制
创建运行时类的对象
通过反射获取运行时类的完整结构
Field,Method,Constructor,Superclass,Interface,Annotion
- 实现的全部接口
- 所继承的父类
- 全部的构造器
- 全部的方法
- 全部的field
- 注解
Class cl = Class.forName("com.fans.annotion_test.Person");
cl.getName();
cl.getSimpleName();
cl.getPackage().getName();
Field[] fields = cl.getFields();//只能找到public属性
fields = cl.getDeclaredFields();//可以找到全部属性
Field name = cl.getDeclaredField("name");
Method[] methods = cl.getMethods();//获取本类以及父类public方法
methods = cl.getDeclaredMethods();//获取本类所有方法
Method method = cl.getMethod("getAge",null);
method = cl.getMethod("setAge", int.class);
Constructor constructor = cl.getDeclaredConstructor(String.class,int.class);
Class cl = Class.forName("com.fans.annotion_test.Person");
Person person = (Person) cl.newInstance();//默认无参构造器,没有无参构造器报错
Constructor constructor = cl.getDeclaredConstructor(String.class,int.class);
Person person1 = (Person) constructor.newInstance("feng",10);
//反射方法
Method method = cl.getMethod("setAge", int.class);
method.invoke(person1,10);
//反射属性,不能直接操作私有属性,需要关闭程序的安全检测
Field field = cl.getDeclaredField("name");
field.setAccessible(true);
field.set(person1,"haha");
性能问题
反射操作泛型
java采用泛型擦除的机制来引入泛型,java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和强制转换问题,但是一旦编译完成,所有和泛型有关的类型全部擦除
public static void main(String[] args) throws NoSuchMethodException {
Class test8Class = com.fans.annotion_test.Test8.class;
Method method = test8Class.getMethod("test1", Map.class, List.class);
Type[] genericParameterTypes = method.getGenericParameterTypes();
for(Type type:genericParameterTypes){
if(type instanceof ParameterizedType){
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
for (Type type1:types){
Log.d("--",type1.toString());
}
}
}
}
public void test1(Map<String,Person> map, List<Person> list){
}
反射获取注解信息
public class Test9 {
public static void main(String[] args) throws NoSuchFieldException {
Class cl = Child.class;
Annotation[] annotations = cl.getAnnotations();
DataBase annotation = (DataBase) cl.getAnnotation(DataBase.class);
String value = annotation.value();
Field field = cl.getDeclaredField("age");
FiledA a = field.getAnnotation(FiledA.class);
String name = a.columnName();
}
}
@DataBase("db_child")
class Child{
@FiledA(columnName = "age",type = "int",length = 10)
private int age;
@FiledA(columnName = "name",type = "varchar",length = 10)
private String name;
public Child() {
}
public Child(int age, String name) {
this.age = age;
this.name = name;
}
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;
}
@Override
public String toString() {
return "Child{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface DataBase{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FiledA{
String columnName();
String type();
int length();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface DataBase{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FiledA{
String columnName();
String type();
int length();
}