您的位置:首页 > 汽车 > 新车 > java——反射与注解

java——反射与注解

2025/1/29 14:02:48 来源:https://blog.csdn.net/m0_70718945/article/details/141182696  浏览:    关键词:java——反射与注解

一、Junit单元测试

1.Junit介绍

概述:Junit是一个单元测试框架,可以代替main方法去执行其他的方法

作用:单独执行一个方法,测试该方法是否能跑通

注意:Junit是第三方工具,所以使用之前需要导入jar包

2.Junit的基本使用(重点)

  • 导入Junit的jar包

  • 定义一个方法,在方法上写注解:@Test

  • 执行方法:

     a点击该方法的左边的绿色按钮,点击执行run执行->单独执行一个指定的方法

     b:如果想要执行所有带@Test的方法,点击类名左边的绿色按钮,点击run执行->执行当前类中所有带@Test的方法

Junit的注意事项

@Test不能修饰static方法

@Test不能修饰带参数的方法

@Test不能修饰带返回值的方法

import org.junit.Test;public class Demo01Junit {@Testpublic void add(){System.out.println("我是@Test的执行add方法");}@Testpublic void delete(){System.out.println("我是@Test的执行delete方法");}
}

Junit相关注解

@Before:在@Test前执行,有多少@Test执行,@Before就执行多少次->都是用作初始化一些数据

@After:在@Test之后执行,有多少个@Test执行,@After就执行多少次->用作释放资源使用

import org.junit.After;
import org.junit.Before;
import org.junit.Test;public class Demo02Junit {@Testpublic void add(){System.out.println("我是@Test的执行add方法");}@Testpublic void delete(){System.out.println("我是@Test的执行delete方法");}@Beforepublic void methodBefore(){System.out.println("我是Before执行的方法");}@Afterpublic void methodAfter(){System.out.println("我是After执行的方法");}
}

其他注解:(了解)

@Beforeclass:在@Test之前执行,只执行一次,可以修饰静态方法

@AfterClass:在@Test之后执行,只执行一次,可以修饰静态方法

二、反射

1.介绍

反射的概述:解剖class对象的一个技术

问题:能解剖class对象的啥呢?

 a:解剖出成员变量:赋值

 b:解剖出成员方法:调用

 c:解剖出构造方法:new对象

用反射的好处:让代码变得更通用,更灵活

怎么学反射?

 a:将反射看成是一套API来学

 b:同伙案例,体会好处

问题:玩反射,最开始的一步是干啥?

 获取class对象

class对象:是class文件对应的对象

Class类:描述class的对象的类叫做class类

2.反射之获取class对象

方式一:调用object中的getclass方法:

  Class<?> getClass()

方式二:不管是基本类型还是引用类型,jvm都为其提供了一个静态成员:class

方式三:Class类中的静态方法:

  Static Class<?>  forName(String  className)

                    ClassName:传递的是类的全限定名(包名,类名)

import org.junit.Test;public class Demo01GetClass {@Testpublic void get1() throws Exception{/* 1.调用object中的getclass方法:Class<?> getClass()*/Person person = new Person();Class<? extends Person> aClass = person.getClass();System.out.println(aClass);System.out.println("=====================");
//2.不管是基本类型还是引用类型,jvm都为其提供了一个静态成员:classClass<Person> aClass1 = Person.class;System.out.println(aClass1);System.out.println("===========");/* 3.Class类中的静态方法:Static Class<?>  forName(String  className)ClassName:传递的是类的全限定名(包名,类名)*/Class<?> aClass2 = Class.forName("com.ykm.b_reflect.Person");System.out.println(aClass2);System.out.println(aClass1==aClass2);}
}

三种获取class对象的方式最通用的一种

方式三:Class类中的静态方法:

  Static Class<?>  forName(String  className)

                    ClassName:传递的是类的全限定名(包名,类名)

原因:参数String形式可以和properties文件结合使用

开发中最常用的是哪一种

直接类名.class->最方便使用

3.获取Class对象中的构造方法

(API)找对象方法获取功能

获取所有public的构造方法

Class类中的方法:

  Constructor<?>[]  getConstructors()  ->获取所有public的构造

import java.lang.reflect.Constructor;public class Demo03GetConstructor {public static void main(String[] args) {//获取Class对象Class<Person> aClass = Person.class;//获取所有public的构造Constructor<?>[] constructors = aClass.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println(constructor);}}
}

4.获取空参构造_public

 Constructor<T>  getConstructor(Class<?>.....parameterTypes)  ->获取指定的public的构造

               parameterTypes:参数类型,可变参数,可以传0个或者多个参数

如果获取的是空参构造:参数不写

如果是获取的是有参构造:参数写参数类型的Class对象

Constructor类中的方法:

  NewInstance(Object...intargs)->创建对象

               .intargs:传递的是构造方法中的实参

如果根据无参构造new对象,initargs不写了

如果根据有参构造new对象,initargs传递实参

import java.lang.reflect.Constructor;public class Demo04GetConstructor {public static void main(String[] args) throws Exception{//获取Class对象Class<Person> aClass = Person.class;Constructor<Person> constructor = aClass.getConstructor();System.out.println(constructor);/** 好比是person  person=new  person()* */Person person = constructor.newInstance();System.out.println(person);}
}

5.利用空参构造创建对象的快捷方式_public

Class类中的方法:

T   newInstance()->.根据空参构造创建对象

前提:被反射的类中必须有public的空参构造

import java.lang.reflect.Constructor;public class Demo05GetConstructor {public static void main(String[] args) throws Exception{//获取Class对象Class<Person> aClass = Person.class;Constructor<Person> constructor = aClass.getConstructor(String.class, Integer.class);System.out.println(constructor);//创建对象Person person = constructor.newInstance("名", 18);System.out.println(person);}
}

6.利用反射获取有参构造并创建对象_public

Class类中的方法:

Constructor<T>  getConstructor(class<?>.......parameterTypes)->获取指定的public的构造

parameterTypes:可变参数,可以传递0个或者多个参数

如果获取的是空参构造:参数不用写

如果获取的是有参构造:参数写参数类型的class对象

Constructor类中的方法:

T  newInstance(Object.....initargs)->创建对象

initargs:传递的是构造方法的实参

如果根据无参构造new对象,initargs不写了

如果根据有参构造new对象,initargs传递实参

import java.lang.reflect.Constructor;public class Demo06GetConstructor {public static void main(String[] args) {Class<Person> aClass = Person.class;Constructor<?>[] dc = aClass.getDeclaredConstructors();for (Constructor<?> constructor : dc) {System.out.println(constructor);}}
}

7.利用反射获取私有构造(暴力反射)

Constructor<?>[]  getDeclaredConstructors()获取所有的构造方法,包括private

Constructor<T>  getDeclaredConstructor(类<?>......parameterTypes)->获取指定构造,包括private

parameterTypes:参数类型的class对象

Constructor有一个父类叫做AccessibleObject,里面有一个方法

void setAccessible(boolean  flag)->.修改访问权限

flag为true:解除私有权限

import java.lang.reflect.Constructor;public class Demo07GetConstructor {public static void main(String[] args)throws Exception {Class<Person> aClass = Person.class;Constructor<Person> dc = aClass.getDeclaredConstructor(String.class);dc.setAccessible(true);//接触私有权限->暴力反射Person person = dc.newInstance("名");System.out.println(person);}
}

8.反射成员方法

(1)利用反射获取所有成员方法_public

Class类中方法:

 Method[] getMethods()->获取所有public的方法,包括父类中的public方法

(2)反射之获取方法(有参,无参)_public

Class类中的方法:

  Method  getMethod(String  name,Class<?>.....parameterTypes)获取指定的public的成员方法

   Name:传递方法名

   ParameterTypes:方法参数类型的class对象

调用方法:Method对象中的方法

Object  invoke(Object  obj,Object.....args)->执行方法

      Obj:根据构造new出来的对象

      Args:方法实参->如果有参数,直接传递实参;否则不用传

9.反射成员变量

Class类中的方法:

Filed[] getFields()->获取所有public的属性

Filed[] getDeclaredFields()->获取所有属性,包括private的

获取指定的属性

Class类中的方法:

Filed   getField(String  name)->获取指定public的属性

Filed   getDeclaredField(String  name)->获取指定属性,包括private的

Field类中的方法:

Void  set(Object  obj,Object  value)->为属性赋值,相当一Javabean中的set方法

Obj:对象

Value:赋予的值

Object  get(Object  obj)->获取属性值

    Obj:对象

import java.lang.reflect.Field;public class Demo08GetFiled {public static void main(String[] args)throws Exception {//  method01();//  method02();method03();}/*Filed   getDeclaredField(String  name)->获取指定属性,包括private的* */private static void method03() throws Exception{Class<Student> studentClass = Student.class;Student student = studentClass.newInstance();Field name = studentClass.getDeclaredField("name");//解除私有权限name.setAccessible(true);//调用set方法赋值name.set(student,"名");//调用getObject o = name.get(student);System.out.println(o);}/**Filed   getField(String  name)->获取指定public的属性** */private static void method02() throws Exception{Class<Student> studentClass = Student.class;Student student = studentClass.newInstance();Field age = studentClass.getField("age");//调用set方法赋值age.set(student,10);//调用getObject o = age.get(student);System.out.println(o);}private static void method01() {Class<Student> studentClass = Student.class;Field[] fields = studentClass.getFields();for (Field field : fields) {System.out.println(field);}System.out.println("=============");Field[] df = studentClass.getDeclaredFields();for (Field field : df) {System.out.println(field);}}
}

10.反射之操作私有方法

Method[]  getDeclareMethods()

Method[]  getDeclareMethod(String  name,类<?>.....parameterTypes)->获取执行成员方法,包括private

                  name:传递方法名

                 parameterTypes:方法参数类型的class对象

解除私有权限:void  setAccessible(boolean  flag)

import java.lang.reflect.Method;public class Demo09GetMethod {public static void main(String[] args) throws Exception {//  method01();// method02();// method03();method04();}/** 反射指定的方法包括private* */private static void method04()throws Exception {Class<Person> aClass = Person.class;Person person = aClass.newInstance();Method eat = aClass.getDeclaredMethod("eat");eat.setAccessible(true);eat.invoke(person);}/*** 获取所有成员方法包括private* */private static void method03() {Class<Person> aClass = Person.class;Method[] dm = aClass.getDeclaredMethods();for (Method method : dm) {System.out.println(method);}}/** 获取指定的public的方法* */private static void method02()  throws  Exception{Class<Person> aClass = Person.class;//创建对象Person person = aClass.newInstance();Method setName = aClass.getMethod("setName", String.class);setName.invoke(person,"名");System.out.println(person);//好比调用tostring方法System.out.println("=============");Method getName = aClass.getMethod("getName");Object invoke = getName.invoke(person);System.out.println(invoke);}/** 获取所有public的方法** */private static void method01() {Class<Person> aClass = Person.class;Method[] method = aClass.getMethods();for (Method method1 : method) {System.out.println(method1);}}
}

三、注解

1.注解的介绍

引用数据类型:类  数组  接口   枚举   注解

jdk1.5版本的新特性->一个引用数据类型和类,接口,枚举是同一个层次的

作用:

说明:对代码进行说明,生成doc文档(API文档)

检查:检查文档是否符合条件   @Override(会用)  @FunctionalInterface

分析:对代码进行分析,起到了代替配置文件的作用(会用)

JDK中的注解:

  @Override->检测此方法是否为重写方法

           jdk1.5版本,支持父类的方法重写

          jdk1.6版本,支持接口的方法重写

2.注解的定义以及属性的定义格式

大家需要知道的是,咱们这里说的注解属性,其实本质上是抽象方法,但是我们按照属性来理解,好理解,因为到时候使用注解的时候,需要=为其赋值

定义:

public  @interface  注解名{

}

定义属性:增强注解的作用

数据类型  属性名()->此属性没有默认值,需要在使用注解的时候为其赋值

数据类型  属性名()  default  值->此属性有默认值,如果有需要,还可以二次赋值

注解中能定义什么类型的属性呢?

8种基本类型

String类型,Class类型,枚举类型,注解类型

以及以上类型的一维数组

public @interface Book {//书名String bookName();//作者String[]  author();//价格int price();//数量int count() default 10;
}

注解的使用

就是为注解中的属性赋值

使用位置:类,方法,成员变量,局部变量,参数位置等

使用格式

  @注解名(属性名=值,属性名=值.....)

  如果属性中有数组:@注解名(属性名={元素一,元素二.......})

@Book(bookName = "水浒传",author = "施耐庵",price = 50,count = 20)
public class BookShelf {}

注解注意事项:

空注解可以直接使用->空注解就是注解中没有任何的属性

不同位置的可以使用一样的注解,但是同样的位置不能使用一样的注解

使用注解时,如果此注解中有属性,注解中的属性一定要赋值,如果有多个属性用,隔开

如果注解中的属性有数组,使用{}

如果注解中的属性值有默认值,那么我们不必要写,也不用重新赋值,反之必须协商

如果注解种只有一个属性,并且属性名叫value,那么使用注解的时候,属性名不用写,直接写值(包括单个类型,还包括数组)

注解解析的方法->AnnotatedElement接口

注解的解析:说白了就是将注解中的属性值获取出来

注解的解析涉及到的接口:AnnotatedElement接口

3.元注解

概述:元注解就是管理注解的注解

从那些方面管理呢?

  a:控制注解的使用位置

     控制注解是否能在类(方法、构造)上使用

   b:控制注解的生命周期(如加载位置)

控制注解是否能在源码(class、内存)中出现

怎么使用

a:@Target:控制注解的使用位置

属性:ElementType[]  value();

    ElementType是一个枚举,里面的成员可以类名直接调用

ElementType中的成员:

 TYPE:控制注解能使用在类上

FIELD:控制注解能使用在属性上

METHOD:控制注解能使用在方法上

PARAMETER:控制注解能使用在参数上

CONSTRUCTOR:控制注解能使用在构造上

LOCAL_VARIABLE:控制注解能使用在局部变量上

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;@Target({ElementType.TYPE,ElementType.METHOD})
public @interface Book {//书名String bookName();//作者String[]  author();//价格int price();//数量int count() default 10;
}

四、枚举

1.介绍

概述:五大引用数据类型之一(类  数组  接口  注解  枚举)

定义:

   Public  enum  枚举类名{  }

所有的枚举为父类都是Enum

定义枚举值

 a:枚举值特点:都是static  final,但是定义的时候不要写出来,写出来报错

                   写完所有的枚举值之后,最后加个;枚举值名字要大写->开发习惯

 b:类名直接调用

c:注意:每一个枚举值都是当前枚举类的对象

问题:枚举类中的枚举值都是什么类型的呢?  本类类型

枚举类中其他成员:构造

在枚举类中定义的构造,默认的都是private的

枚举的使用场景:表示对象的状态

public enum State {//State  WEIFUKUAN=new State()//State  WEIFUKUAN=new State("未付款")WEIFUKUAN("未付款"),YIFUKUAN("已付款"),WEIFAHUO("未发货"),YIFAHUO("已发货");private String  name;State() {}State(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

2.枚举的方法

方法名

说明

String  toString()返回枚举值的名字
values()返回所有与的枚举值
valueOf(String str)将一个字符串转成枚举类型
public class Test01 {public static void main(String[] args) {State weifahuo = State.WEIFAHUO;System.out.println(weifahuo.getName());System.out.println("================");String s = State.WEIFUKUAN.toString();System.out.println(s);System.out.println("=========");State[] values = State.values();for (State value : values) {System.out.println(value);}}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com