学习java Day07
注解
- 注解和注释不同,注解可以在代码编译,类加载,运行时分别起到作用,被JVM虚拟机读取,框架基本都靠注解+反射进行设计,在不改变原有代码和逻辑的情况下,在源代码注入补充信息。
- 例如在写类时重写toString方法时上面的**@Override**就是一个注解,如果写错了就会提醒
- 元注解:表示注解注解的注解,点进@Override里看到@Target,@Retention就是元注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
- 自定义注解:格式 public @interface 注解名{ 参数类型 参数名(); }
// 自定义注解
@Retention(RetentionPolicy.RUNTIME) // 自定义的注解基本都使用RUNTIME表示运行时还有效
@Target({ElementType.TYPE,ElementType.METHOD}) //表示这个注解作用的范围在类上和方法上
public @interface MyFirstAnnotation{
String name(); // 无默认值 使用注解时一定要定义定义这个参数
int num() default 12; // 有默认值 使用注解时可以不用写这个值
String[] value(); // 如果注解只有一个参数,且参数是value则可以省略value直接写值
}
// 使用自定义注解
@MyFirstAnnotation(name="xxx",value={"111","222"})
public class Test{
@MyFirstAnnotation(name = "xyy",num = 20,value = "123")
public void show(){
}
}
反射
- 反射是通过类对象 来进行操作的,类对象是类加载是产生的,我们只能获取: 3种方式 但是一个类只能有一个类对象
所以这三个获得的是同一个类对象- Class c1 = 对象名.getClass();
- Class c2 = 类名.class;
- Class c3 = Class.forName(“全类名”);
- 类对象能获得类的全部信息(属性包括私有属性,方法,注解,构造方法)
- 通过反射执行效率比直接操作对象低
- 通过反射获取字段(属性)
class Person{
public String color;
protected int n;
int m;
private String area;
}
public class Student extends Person{
private int id;
public String name;
protected int op;
int t;
}
public class ReflectTest {
public static void main(String[] args) {
Class studentClass = Student.class;
Field[] fields = studentClass.getFields(); // 获取所有public修饰的字段,包括继承的
for (Field field : fields) {
System.out.println(field);
}
System.out.println("===================");
Field[] declaredFields = studentClass.getDeclaredFields();// 获取本类的所有字段
for (Field declaredfields : declaredFields) {
System.out.println(declaredfields);
}
}
}
// 结果
public java.lang.String Ten_Four.Reflect.Student.name
public java.lang.String Ten_Four.Reflect.Person.color
===================
private int Ten_Four.Reflect.Student.id
public java.lang.String Ten_Four.Reflect.Student.name
protected int Ten_Four.Reflect.Student.op
int Ten_Four.Reflect.Student.t
// 获取指定字段
Student student = new Student();
Class studentClass = Student.class;
Field color = studentClass.getDeclaredField("name");
color.set(student,"xxx");
System.out.println(student.name); // xxx
- 获取构造方法 创建对象
public class Student extends Person{
private int id;
public String name;
protected int op;
int t;
public Student(int id, String name, int op, int t) {
this.id = id;
this.name = name;
this.op = op;
this.t = t;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", op=" + op +
", t=" + t +
'}';
}
}
public class ReflectTest {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class studentClass = Student.class;
Constructor constructor = studentClass.getConstructor(int.class, String.class, int.class, int.class); // 可能有重载必须指定参数类型
Student stu = (Student)constructor.newInstance(12, "Yes", 14, 13); // 创建对象
System.out.println(stu);
// 操作私有的 必须先设置 字段名.setAccessible(true)
Field id = studentClass.getDeclaredField("id");
id.setAccessible(true);
int str = (Integer) id.get(stu); // 字段对象.get(字段属于类的真实对象) 得到这个真实对象的该字段值
System.out.println(str);
}
}
// 结果
Student{id=12, name='Yes', op=14, t=13}
12
- 获取成员方法
public class Student {
public void show(){
System.out.println("show time");
}
public static void hello(int nu,int un){
System.out.println("==="+nu+un+"===");
}
}
public class ReflectTest {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
Class studentClass = Student.class;
Student student = new Student();
Method show = studentClass.getDeclaredMethod("show", null);
Method hello = studentClass.getDeclaredMethod("hello", int.class,int.class);
// 方法执行 invoke(对象名,参数)
show.invoke(student,null); //方法,没有参数 ,则写null
hello.invoke(null,13,14); // 如果是静态方法,对象传入null
}
}
利用class和ClassLoad加载文件
// 加载的是src目录下的文件 不能加/
InputStream resourceAsStream = ReflectTest.class.getClassLoader().getResourceAsStream("a.txt");
// 不加/ 表示加载当前包下的文件
InputStream resourceAsStream1 = ReflectTest.class.getResourceAsStream("a.txt");
// 加上/表示加载的是src目录下的 和classLoad一样
InputStream resourceAsStream2 = ReflectTest.class.getResourceAsStream("/a.txt");