一、类加载器
1.java文件运行过程:
java源文件(.java)—(编译器编译)—>字节码文件(.class)—(类加载器加载)—>字节码对象(Class)
2.什么是类加载器,作用是什么?
类加载器就加载字节码文件(.class)
3.类加载器的种类
类加载器有三种,不同类加载器加载不同的
1)BootStrap:引导类加载器:加载都是最基础的文件
2)ExtClassLoader:扩展类加载器:加载都是基础的文件
3)AppClassLoader:应用类加载器:三方jar包和自己编写java文件
4.怎么获得类加载器?
ClassLoader 字节码对象.getClassLoader();
示例代码:
//获得Demo字节码文件的类加载器
Class clazz = Demo.class;//获得Demo的字节码对象
ClassLoader classLoader = clazz.getClassLoader();//获得类加载器
//getResource的参数路径相对classes(src),可以获得classes(src)下的任何资源
//获得classes(src)下的jdbc.properties资源
String path = classLoader.getResource("cn/zsl/test/jdbc.properties").getPath();
二、注解 @xxx
1.什么是注解,注解作用
注解就是符合一定格式的语法 @xxxx
注解作用:
注释:在阅读程序时清楚----给程序员看的
注解:给jvm看的,给机器看的
注解在目前而言最主流的应用:代替配置文件
关于配置文件与注解开发的优缺点:
注解优点:开发效率高 成本低
注解缺点:耦合性大 并且不利于后期维护
2.jdk5提供的注解
@Override:告知编译器此方法是覆盖父类的
@Deprecated:标注过时
@SuppressWarnings:压制警告
注:不同的注解只能在不同的位置使用(方法上、字段上、类上)
3.自定义注解
1)怎样去编写一个自定义的注解
关键字:@interface
注解的属性:
语法:返回值 名称();
注意:如果属性的名字是value,并且注解的属性值有一个,那么在使用注解时可以省略value
注解示例1:
public @interface MyAnno {
String name();
//如果该注解只有一个value属性,那么在使用注解的时候可以在括号中直接传值
// String value();
//default表示该注解的默认值,当设置了默认值,则使用该注解的时候该属性可以不传
int age() default 20;
}
使用注解1:
public class Demo {
//age不传则默认为20
@MyAnno(name = "zhangsan")
public void show(){
System.out.println();
}
}
注解示例2:
public @interface MyAnno {
String value();
String name() default "lisi";
int age() default 20;
}
使用注解2:
public class Demo {
//如果注解中有一个名为value的属性,并且不存在其他属性或者其他属性都给了默认值,那么使用注解的时候就可以省略键值对的键直接给值
@MyAnno("zhangsan")
public void show(){
System.out.println();
}
}
2)元注解
元注解:代表修饰注解的注解,作用:限制定义的注解的特性
@Retention
SOURCE: 注解在源码级别可见
CLASS:注解在字节码文件级别可见
RUNTIME:注解在整个运行阶段都可见
@Target
代表注解修饰的范围:类上使用,方法上使用,字段上使用
FIELD:字段上可用此注解
METHOD:方法上可以用此注解
TYPE:类/接口上可以使用此注解
因此如果要通过字节码解析注解,就必须把该注解的可见范围设置为RUNTIME,这样在运行字节码文件的时候才能获取到该注解,否则会报空指针。
注解示例3:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
String name() default "lisi";
String value();
int age() default 20;
}
使用注解3:
public class Demo {
@MyAnno("zhangsan")
public void show(){
System.out.println();
}
}
解析注解3:
public class TestMyAnno {
public static void main(String[] args) {
//解析show方法上面的@MyAnno
//直接目的:获得show方法上的@MyAnno中的参数
try {
//获得show方法的字节码对象
Class clazz = Demo.class;
Method method = clazz.getMethod("show",null);
//获得show方法上的@MyAnno
MyAnno annotation = method.getAnnotation(MyAnno.class);
//获得@MyAnno上的属性值
System.out.println(annotation.name());
System.out.println(annotation.age());
System.out.println(annotation.value());
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}
}
打印结果:
lisi
20
zhangsan