注解与反射
1.注解Annotation
1.1什么是注解
2.内置注解
package com.Annotation;
public class Test01 extends Object{
@Override //重写的注解
public String toString() {
return super.toString();
}
//Deprecated 不推荐程序员使用,但是可以使用,或者存在更好的方式
@Deprecated
public static void test(){
System.out.println("Deprecated");
}
@SuppressWarnings("all")//用来消除警告
public void test2(){
}
public static void main(String[] args) {
test();
}
}
3.自定义注解,元注解
1.元注解
package com.Annotation;
import java.lang.annotation.*;
//测试元注解
@MyAnnotation
public class Test02 {
@MyAnnotation
public void test(){
}
}
//@Target 表示我们的注解可以用在哪些地方
@Target(value = {ElementType.TYPE,ElementType.ANNOTATION_TYPE,ElementType.METHOD})
//@Retention 表示我们的注解在什么地方有效
@Retention(value = RetentionPolicy.RUNTIME)
//@Documented 表示是否将我们的注解生成在javadoc中
@Documented
//@Inherited 子类可以继承父类
@Inherited
//定义一个注解
@MyAnnotation
@interface MyAnnotation{
}
2.自定义注解
package com.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//自定义注解
public class Test03 {
//注解可以显示赋值,如果没有默认值,我们必须给注解赋值
@MyAnnotation2(age=18)
public void test(){}
//只有注解默认参数名为value时,才可以省略
@MyAnnotation3( "胡歌")
public void test2(){}
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
//注解的参数:参数类型+参数名();
String name() default "";
int age() ;
int id() default -1;//如果默认值为-1,代表不存在, indexOf,如果找不到返回-1.
String[] schools() default {"清华大学","北京大学"};
}
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
String value();
}
2.反射Reflection
-
优点:可以实现动态创建对象和编译,体验出很大的灵活性
-
缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉jvm,我们希望做什么并且它满足我们的要求,这类操作总是慢于直接执行相同的操作。
2.1获得class类的实例
package com.Annotation.Reflection; public class Test02 { 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()); //方式二:format获得 Class c2 = Class.forName("com.Annotation.Reflection.Student"); System.out.println(c2.hashCode()); //方式三:通过类名,class获得 Class c3 = Student.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 = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } } class Student extends Person{ public Student(){ this.name="学生"; } } class Teacher extends Person{ public Teacher() { this.name="老师"; } }
2.2哪些类型可以有Class对象?
- class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类。
- interface:接口
- []:数组
- enum:枚举
- annotation:注解@interface
- primitive type:基本数据类型
- 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;//void
Class c9=Class.class;//Class
package com.Annotation.Reflection;
/**
*1.加载到内存,会产生一个类对应class对象
* 2.链接,链接结束后m=0;
* 3.初始化
* <clinit>(){
* System.out.println("A类静态代码块初始化");
* m=300;
* m=100;
* }
*/
public class Test05 {
public static void main(String[] args) {
A a=new A();
System.out.println(a.m);
}
}
class A{
static{
System.out.println("A类静态代码块初始化");
m=300;
}
static int m=100;
public A(){
System.out.println("A类的无参构造初始化");
}
}
/**
*测试类什么时候会初始化
*/
public class Test06 {
static {
System.out.println("main方法被加载");
}
public static void main(String[] args) {
//主动引用
//Son son=new Son();
//反射也会产生主动引用
//Class.forName("com.Annotation.Reflection.Son");
//不会产生类的引用的方法
//System.out.println(Son.b);
// Son[] array=new Son[5];
System.out.println(Son.M);
}
}
class Father{
static{
System.out.println("父类被加载");
}
static int b=2;
}
class Son extends Father{
static {
System.out.println("子类被加载");
int m=0;
}
private int m=300;
static final int M=1;
}
2.3通过反射获取运行时类的完整结构
Field(成员变量),Method(方法),Constructor(构造器),SuperClass(父类),Interface(接口),Annotation(注解)
package com.Annotation.Reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 获得类的信息
*/
public class Test08 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.Annotation.Reflection.user");
//获得类的名字
System.out.println(c1.getName());
System.out.println(c1.getSimpleName());
//获取类的属性
Field[] field = c1.getFields();//只能找到public属性
field =c1.getDeclaredFields();//找到所有的属性
for (Field field1 : field) {
System.out.println(field1);
}
System.out.println("=============================");
//获得指定属性的值
Field name = c1.getDeclaredField("name");
System.out.println(name);
//获得类的方法
Method[] method = c1.getMethods();//获得本类及其父类的全部public方法
for (Method method1 : method) {
System.out.println("正常的: "+method1);
}
System.out.println("=============================");
method =c1.getDeclaredMethods();//获得本类的所有方法
for (Method method1 : method) {
System.out.println("getDeclaredMethods: "+method1);
}
//获得指定的方法
System.out.println("=============================");
Method getName = c1.getMethod("getName");
Method setName = c1.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);
System.out.println("=============================");
//获得指定的构造器
Constructor[] con = c1.getConstructors();//获得public的构造器
for (Constructor constructor : con) {
System.out.println(constructor);
}
con = c1.getDeclaredConstructors();//获得所有的构造器
for (Constructor constructor : con) {
System.out.println("515 "+constructor);
}
//获得指定的构造器
Constructor con1 = c1.getConstructor(String.class, int.class, int.class);
System.out.println("获得指定的构造器 "+con1);
}
}
2.4通过反射动态的创建对象
import java.lang.reflect.Method;
/**
*动态的创建对象,通过反射
*/
public class Test09 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得一个class对象
Class c1 = Class.forName("com.Annotation.Reflection.user");
// //构造一个对象
// user use = (user)c1.newInstance();//本质调用了类的无参构造器
// System.out.println(use);
//
// //通过构造器来创造对象
// Constructor Constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
// user use2 = (user)Constructor.newInstance("派大星", 101, 10);
// System.out.println(use2);
//通过反射调用普通方法
user use3 = (user) c1.newInstance();
//通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
setName.invoke(use3,"派大星啊啊啊");
System.out.println(use3.getName());
//通过反射操作属性
user use4 = (user) c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,需要设置可访问性--setAccessible(true);
name.setAccessible(true);//设置可访问性,true可以进行访问
name.set(use4,"派小星");
System.out.println(use4.getName());
}
}
2.5通过反射获取注解信息
ackage com.Annotation.Reflection;
import java.lang.annotation.*;
import java.lang.reflect.Field;
/**
*反射操作注解
*/
public class Test12 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.Annotation.Reflection.pop");
//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获得注解的value的值。
pxx pxx = (pxx)c1.getAnnotation(pxx.class);
String value = pxx.value();
System.out.println(value);
//获得类指定的注解
Field f1 = c1.getDeclaredField("name");
filed annotation = f1.getAnnotation(filed.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@pxx("db_sutdent")
class pop{
@filed(columnName = "db_id",type="int",length = 10)
private int id;
@filed(columnName = "db_name",type="varchar",length = 3)
private String name;
@filed(columnName = "db_aeg",type="int",length = 10)
private int age;
public pop() {
}
public pop(int id, String name, int age) {
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;
}
@Override
public String toString() {
return "pop{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface pxx{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface filed{
String columnName();
String type();
int length();
}
推荐大家去b站看狂神的java视频