元注解:
元注解的作用是负责解释其他注解,java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明,(@Target,@Retention,@Documented,@Inherited)
@Target:用来描述注解的使用范围(即被描述的注解可以用在什么地方)
@Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(SOURCE<CLASS<RUNTIME)
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
package controller;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Linyajing
*/
public class annoDemo1 {
@MyAnnotion1(age = 18,name="linyajin")
public void test1(){}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotion1{
//注解的参数:参数类型+参数名();
String name() default "";
int age();
int id() default -1;
String[] schools() default {"beilei","dizhi"};
}
Class类
对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE都为其保留一个不变Class类型的对象,一个Class对象包含了特定某个结构的有关信息
Class本身也是一个类
Class对象只能由系统建立对象
一个加载的类在JVM中只会有一个class实例
一个Class对象对应的是一个加载到JVM的一个.class文件
每个类的实例都会记得自己是由哪个Class实例所生成
通过Class可以完整的地得到一个类中的所有被加载的结构
Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象
获得Class的方法
package controller;
import javax.security.auth.Subject;
import javax.sound.midi.Soundbank;
import java.lang.management.ThreadInfo;
import java.sql.SQLOutput;
import java.util.SortedMap;
/**
* @author Linyajing
*/
public class ClassTest {
public static void main(String[] args) throws ClassNotFoundException{
Person person = new Student();
System.out.println("这是"+person.name);
//方式一:通过对象获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());
//方式二:forname获得
Class c2= Class.forName("controller.Person");
System.out.println(c2.hashCode());
//方式三:通过类名.class 获得
Class c3 = Person.class;
System.out.println(c3.hashCode());
//方式四:基本内置类型的包装类都有一个type属性
Class c4 = Integer.TYPE;
System.out.println(c4);
//获得父类类型
Class c5 = c1.getSuperclass();
System.out.println(c5);
}
}
class Person{
public String name;
public Person(){}
public Person(String name){
this.name = "LIN";
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person{
public Student(){
this.name = "lin";
}
}
哪些类型可以有Class对象
class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类,
interface:接口
[]:数组
enum:枚举
annotation:注解@interface
primitive type:基本数据类型
void:空
类的加载与ClassLoader的理解
>加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象
>链接:将java类的二进制代码合并到JVM运行状态之中的过程
--验证:确保加载的类信息符合JVM规范,没有安全方面的问题
--准备:正式为变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配
--解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程
>初始化:
--执行类构造器<clinit>()方法的过程,类构造器<clinit>()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的(类构造器是构造类信息的,不是构造该类对象的构造器)
--当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化
--虚拟机会保证一个类<clinit>()方法在多线程环境中被正确加锁和同步。
什么时候会发生类初始化
>类的主动引用(一定会发生类的初始化)
--当虚拟机启动,先初始化main方法所在的类
--new一个类的对象
--调用类的静态成员(除了final常量)和静态方法
--使用java.lang.reflect包的方法对类进行反射调用
--当初始化一个类,如果其父类没有被初始化,则先会初始化他的父类
>类的被动引用(不会发生类的初始化)
--当访问一个静态域时,只有真正生命这个域的类才会被初始化,如,当通过子类引用父类的静态变量,不会导致子类的初始化初始化
--通过数组定义类引用,不会触发此类的初始化
--引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)
类加载器
引导类加载器:用C++编写,是JVM自带的类加载器,负责java平台核心库,用来装在核心类库,该加载器无法直接获取
扩展类加载器:负责jre/lib/ext目录下的jar包或java.ext.dirs指定目录下的jar包装入工作库
系统类加载器:负责java-classpath 或-D java.class.path所指的目录下的类与jar包装入工作,是最常用的加载器
public class Test1 {
public static void main(String[] args) {
//返回系统类加载器
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
//扩展类加载器
ClassLoader classLoader1 = classLoader.getParent();
System.out.println(classLoader1);
//根加载器
ClassLoader classLoader2 = classLoader1.getParent();
System.out.println(classLoader2);
}
}
获得类信息
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.logging.MemoryHandler;
//获得类的信息
public class fieldTest {
public static void main(String[] args) throws Exception {
Class c1=Class.forName("User");
//找到类的名字
System.out.println(c1.getName());//获得包名+类名
System.out.println(c1.getSimpleName());//获得类名
System.out.println("==================");
//获得类的属性
Field[] fields = c1.getFields();//只能获得public属性
for(Field field :fields){
System.out.println(field);
}
System.out.println("==================");
Field[] fields2 = c1.getDeclaredFields();//获得全部属性
for(Field field :fields2){
System.out.println(field);
}
System.out.println("==================");
//获得指定属性的值
Field name = c1.getDeclaredField("name");
System.out.println(name);
System.out.println("==================");
//获得类的方法
Method[] methods = c1.getMethods();//获得本类public及父类方法
for(Method method : methods){
System.out.println("正常的:"+method);
}
methods = c1.getDeclaredMethods();//获得奔雷方法
for(Method method : methods){
System.out.println("getDeclare:"+method);
}
//获得指定方法
Method getName = c1.getMethod("getName",null);
Method setName=c1.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);
//获得指定的构造器
Constructor[] constructors = c1.getConstructors();
for(Constructor constructor : constructors){
System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors();
for(Constructor constructor : constructors){
System.out.println("++++"+constructor);
}
//获得指定的构造器
Constructor constructor = c1.getDeclaredConstructor(String.class,int.class,int.class);
System.out.println("指定构造器:"+constructor);
}
}
通过反射得到注解信息
import java.lang.annotation.*;
import java.lang.reflect.Field;
public class AnnotationTest {
public static void main(String[] args) throws ClassNotFoundException,NoSuchFieldException{
Class c1 = Class.forName("Student");
//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation :annotations){
System.out.println(annotation);
}
//获得注解的value的值
TableLin tableLin = (TableLin)c1.getAnnotation(TableLin.class);
String value = tableLin.value();
System.out.println(value);
//获得类指定的注解
Field f = c1.getDeclaredField("name");
FiledLin annotion = f.getAnnotation(FiledLin.class);
System.out.println(annotion.columeName());
System.out.println(annotion.length());
System.out.println(annotion.type());
}
}
@TableLin("db_student")
class Student{
@FiledLin(columeName = "db_li",type = "int",length = 10)
private int id;
@FiledLin(columeName = "db_name",type = "varchar",length = 200)
private String name;
@FiledLin(columeName = "db_age",type = "int",length = 10)
private int age;
public Student(){}
public Student(int id,int age,String name){
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//类名注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableLin{
String value();
}
//属性注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FiledLin{
String columeName();
String type();
int length();
}