注解
注解标志: @ 如 @Override。分为JDK注解,元注解,自定义注解
JDK注解
@Override` 重写方法
@Deprecated 已过时
@SuppressWarnings("deprecation") 忽略警告
@SafeVarargs jdk 1.7出现,堆污染,不常用
@FunctionallInterface jdk1.8出现,配合函数式编程拉姆达表达式,不常用
元注解
描述注解的注解。
@Target 表明注解的位置:类上、方法上、属性上
@Retention 注解的生命周期:源文件中、class文件中、运行时
@Inherited 允许子注解继承
@Documented 生成javadoc时会包含注解,不常用
@Repeatable 注解为可重复类型注解,可在同一个地方多次使用,不常用
@Target ElementType.class
描述注解的使用范围:
ElementType.ANNOTATION_TYPE 应用于注释类型
ElementType.CONSTRUCTOR 应用于构造函数
ElementType.FIELD 应用于字段或属性
ElementType.LOCAL_VARIABLE 应用于局部变量
ElementType.METHOD 应用于方法
ElementType.PACKAGE 应用于包声明
ElementType.PARAMETER 应用于方法的参数
ElementType.TYPE 应用于类的元素
@Retention RetentionPlicy.class
定义了注解的生命周期 SOURCE CLASS RUNTIME RetentionPlicy 类中
自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class Test1_Annotation {
public static void main(String[] args) {
}
}
//1,创建自定义注解Test:语法:@interface 注解名
//2、@Target指定注解的位置--ElementType.TYPE是指可以出现在类上
//3、@Retention指定注解的生命周期--RetentionPolicy.SOURCE是指在源码中有效
//@Target( ElementType.METHOD )
@Target( { ElementType.TYPE , ElementType.METHOD } )
@Retention(RetentionPolicy.SOURCE)
@interface Test {
//5、给注解添加属性--注解的语法和java略有不同
String name() default "" ;
String value() default "" ;//8、特殊属性,赋值时可以简写
}
//4、使用自定义的注解Test
//6、使用Test注解时,同时给name属性赋值(没有默认值时)
//@Test(name="hello")
//7、如果name属性有了默认值,我们使用就可以省略赋值
//@Test(value="hello")
@Test("hello") //8.1、如果给value属性赋值,可以简写
class Hello {
// @Test The annotation @Test is disallowed for this location
String name ;
@Test
public void method() {
System.out.println(123);
}
}
反射
Reflection 可在运行时获取一个类的所有信息,可以获取到任何定义的信息(包括成员变量、成员方法、构造器等),并且可以操纵类的字段、方法、构造器等部分
反射 class 类对象
Class.forName("类的全路径");
类名.class
对象.getclass();
常用方法:
获取包名、类名
clazz.getPackage().getName() //包名
clazz.getSimpleName() //类名
clazz.getName() //完整类名
构造方法定义信息
getConstructor(参数类型列表) //获得公开的构造方法
getConstructors() //获得所有公开的构造方法
getDeclaredConstructors() //获得所有的构造方法,包括私有
方法定义信息
getMethods() //获得所有可见的方法,包括继承的
getMethod(方法名,参数类型列表)
getDeclareMethods() //获得本类定义的方法,包括私有,不包括继承
反射新建实例
c.newInstance(); // 执行无参构造
c.newInstance(6,"abc"); //执行有参构造
反射调用成员方法
Method m = c.getDeclareMethod(方法名,参数类型列表)
m.setAccessible(true); //使私有方法允许被调用
m.invoke(实例,参数数据);//让指定的实例来执行该方法
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
//这个类用来测试 反射获取学生类里的所有数据
//Junit单元测试方法: @Test + void + 没有参数
//运行:必须选中方法名,右键,run as , junit test...
public class Test3_Reflection2 {
//利用反射创建对象
@Test
public void showObject() throws Exception {
//1、获取Class对象
Class<?> clazz = Student.class;
//2、利用反射,创建对象
Object obj = clazz.newInstance();//触发了无参构造
//cn.tedu.reflection.Student@443b7951
System.out.println(obj);
//怎么触发含参构造
//指定你想要触发 哪个 含参构造
// clazz.getConstructor(String.class);//触发string类型的含参构造
// clazz.getConstructor(int.class);//触发int类型的含参构造
Constructor c = clazz.getConstructor(String.class , int.class);
Object obj2 = c.newInstance("皮皮霞",20);//给构造方法传参
//cn.tedu.reflection.Student@14514713
//Student [name=皮皮霞, age=20]
System.out.println(obj2);
}
//获取学生类中的成员变量们
@Test
public void showFields() {
//1、获取Class对象
Class<?> clazz = Student.class;
//2、获取所有 公共的 的属性们
Field[] fs = clazz.getFields() ;
//3、遍历数组
for (Field f : fs) {
//4、获取变量名
String name = f.getName() ;
System.out.println(name);
//5、获取变量的类型
String type = f.getType().getName();
System.out.println(type);
}
}
//获取学生类中的构造方法们
@Test
public void showConstructor() {
// 1、获取Class对象
Class<?> clazz = Student.class;
// 2、调用方法
Constructor<?>[] cs = clazz.getConstructors() ;
//3、遍历数组
for(Constructor c : cs) {
//4、获取方法名
String name = c.getName();
System.out.println(name);
//5、获取参数的类型
Class[] cls = c.getParameterTypes() ;
System.out.println( Arrays.toString(cls) );
}
}
// 获取学生类中的成员方法们
@Test
public void showMethod() {
// 1、获取Class对象
Class<?> clazz = Student.class;
// 2、调用方法
Method[] ms = clazz.getMethods();
// 3、遍历数组
for (Method m : ms) {
// 4、获取方法名
String name = m.getName();
System.out.println(name);
//5、获取方法有没有参数
Class<?>[] cls = m.getParameterTypes();
System.out.println( Arrays.toString(cls) );
}
}
@Test
public void showClass() throws ClassNotFoundException {
// 反射Class对象
Class<?> clazz = Class.forName("cn.tedu.reflection.Student");
Class<?> clazz2 = Student.class;
Student s = new Student();
Class<?> clazz3 = s.getClass();
System.out.println(clazz);
System.out.println(clazz2);
System.out.println(clazz3);
}
}
public class Student {
public String name;
public int age;
public Student(){}
public Student(String name,int age){
this.name = name;
this.age = age;
}
public void save(){
System.out.println("save()...");
}
public void show(int num){
System.out.println("show()..."+num);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
暴力反射
import org.junit.Test;
import java.lang.reflect.Method;
import java.util.Arrays;
//这个类用来 测试暴力反射Person
public class Test4_ReflectPrivate {
//暴力反射成员方法
@Test
public void showMethod() throws Exception {
//1、获取Class对象
Class clazz = Class.forName("cn.tedu.reflection.Person");
//2、获取所有的方法们
// clazz.getMethods(); //反射 公共的 资源
//3、暴力反射 -- 所有 方法们 --- getDeclaredMethods()--可以获取公共的或者私有的方法
Method[] ms = clazz.getDeclaredMethods();
for (Method m : ms) {
String name = m.getName();
System.out.println(name);
Class<?>[] cls = m.getParameterTypes();
System.out.println( Arrays.toString(cls) );
}
//4、暴力反射 -- 获取 单个 方法
//getDeclaredMethod(m,n)-m是想要执行的方法名 -n是方法需要的参数类型
Method method = clazz.getDeclaredMethod("show", null);
//5、如何执行
//--invoke(m,n)-m是想让哪个对象执行方法-n是方法需要的参数
//!!设置私有可见
method.setAccessible(true);
Object obj = clazz.newInstance() ;
method.invoke(obj, null) ;
}
}
public class Person {
private String name = "张三";
private int age = 20;
private void show(){
System.out.println("show()...");
}
private void test(int a){
System.out.println("test()..."+a);
}
}