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 {
    @Test
    
    public void add(){
        System.out.println("我是@Test的执行add方法");
    }

@Test

    public 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 {

    @Test

    public void add(){
        System.out.println("我是@Test的执行add方法");
    }

@Test

    public void delete(){
        System.out.println("我是@Test的执行delete方法");
    }


    @Before
    public void methodBefore(){
        System.out.println("我是Before执行的方法");


    }

    @After
    public 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 {
    @Test
    public 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都为其提供了一个静态成员:class
        Class<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,"名");
        //调用get
        Object 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);
        //调用get
        Object 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);
        }
    }
}
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值