7月24日反射,注解,Java8特性

7月24日反射,注解,Java8特性

1.反射

1.1反射概述

反射:
    发生在程序运行期间的动态机制|行为
    是java的唯一动态机制-->反射机制
**Java反射机制,可以实现以下功能:**

    ①在运行时判断任意一个对象所属的类;

    ②在运行时构造任意一个类的对象;

    ③在运行时判断任意一个类所具有的成员变量和方法;

    ④在运行时调用任意一个对象的方法;

    ⑤生成动态代理;

    *

反射的源头:
*   Class<T> Class类型的实例可以用来表示java中运行期间的一个类型
*   Class对象
*
*   Class对象在类第一次加载到内存后就已经存在的,唯一的,不变的,每一个类型只有一个
*   Class对象可以操作这个类的所有内容(属性方法构造器...)
*
如何获取反射的源头:Class对象
*   1.类名.class
*   2.Class.forName(权限定名)  权限定名:包名.类名   -->推荐
*   3.对象.getClass()
public class Class002_Reflect {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.类名.class
        Class<String> cls1 = String.class;
        System.out.println(cls1.toString());

        //2.Class.forName(权限定名)
        Class cls2 = Class.forName("java.lang.String");
        System.out.println(cls2);
        System.out.println(cls2==cls1);

        //3.对象.getClass()
        Class cls3 = "abc".getClass();
        System.out.println(cls3);
        System.out.println(cls3==cls1);

        //获取当前Class对象所表示类型的父类的Class对象
        Class cls4 = cls1.getSuperclass();
        System.out.println(cls4);
        System.out.println(cls4==Object.class);

        //获取基本数据类型的Class对象
        System.out.println(Integer.class);
        System.out.println(int.class);
        System.out.println(int.class==Integer.class);
        System.out.println(Integer.TYPE);
        System.out.println(Integer.TYPE==int.class);
    }
}

class java.lang.String
class java.lang.String
true
class java.lang.String
true
class java.lang.Object
true
class java.lang.Integer
int
false
int
true

1.2 反射操作构造器

反射操作构造器
    构造器<T> getConstructor(类<?>... parameterTypes) 返回一个 构造器对象,该对象反映此 类对象所表示的类的指定公共构造函数。
    构造器<?>[] getConstructors() 返回一个包含 构造器对象的数组, 构造器对象反映了此 类对象所表示的类的所有公共构造函数。
    以上都是获取公共的,被public修饰的构造器
    构造器<T> getDeclaredConstructor(类<?>... parameterTypes) 返回一个 构造器对象,该对象反映此 类对象所表示的类或接口的指定构造函数。
    构造器<?>[] getDeclaredConstructors() 返回 构造器对象的数组, 构造器对象反映由此 类对象表示的类声明的所有构造函数。

反射创建对象
    Class-->T newInstance()  默认调用类型的空构造为对象初始化信息  -->不推荐使用
        不能确定一个类型是否存在空构造,极有可能遇到运行时异常
    Constructor---> T newInstance(Object... initargs) 创建对象的同时调用当前构造器为对象初始化信息
public class Class003_Reflect {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {


        //获取构造器
        Class<User> cls = User.class;

        Constructor[] cons =  cls.getConstructors();
        for(Constructor con:cons){
            System.out.println(con);
        }

        Constructor<User> con = cls.getDeclaredConstructor(String.class,int.class);

        System.out.println(con);

        //创建对象
        //1)
        User user =  User.class.newInstance();
        System.out.println(user);

        //2) 私有内容需要忽略权限使用
        con.setAccessible(true);  //忽略权限
        User user2 = con.newInstance("laopei",1234);
        System.out.println(user2);
    }


}

class User{
    private String name;
    private int pwd;

    //公共的
    public User() {
    }

    public User(String name) {
        this.name = name;
    }
    //私有的
    private User(String name, int pwd) {
        this.name = name;
        this.pwd = pwd;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPwd() {
        return pwd;
    }

    public void setPwd(int pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", pwd=" + pwd +
                '}';
    }
}

public com.yjxxt.reflect.User(java.lang.String)
public com.yjxxt.reflect.User()
private com.yjxxt.reflect.User(java.lang.String,int)
User{name=‘null’, pwd=0}
User{name=‘laopei’, pwd=1234}

1.3反射操作属性

反射操作属性
    字段 getField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定公共成员字段。
    字段[] getFields() 返回一个包含 字段对象的数组, 字段对象反映此 类对象所表示的类或接口的所有可访问公共字段。
    字段 getDeclaredField(String name) 返回 字段对象,该对象反映此 类对象表示的类或接口的指定声明字段。
    字段[] getDeclaredFields() 返回 字段对象的数组, 字段对象反映由此 类对象表示的类或接口声明的所有字段。

    void set(Object obj, Object value) 将指定对象参数上此 字段对象表示的字段设置为指定的新值。
    Object get(Object obj) 返回指定对象上此 字段表示的字段的值。

反射操作方法
    方法 getMethod(String name, 类<?>... parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定公共成员方法。
    方法[] getMethods() 返回一个包含 方法对象的数组, 方法对象反映此 类对象所表示的类或接口的所有公共方法,包括由类或接口声明的那些以及从超类和超接口继承的那些。
    方法 getDeclaredMethod(String name, 类<?>... parameterTypes) 返回 方法对象,该对象反映此 类对象表示的类或接口的指定声明方法。
    方法[] getDeclaredMethods() 返回一个包含 方法对象的数组, 方法对象反映此 类对象表示的类或接口的所有已声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承的方法。

    Object invoke(Object obj, Object... args) 在具有指定参数的指定对象上调用此 方法对象表示的基础方法。
public class Class004_Reflect {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        User user = new User("zhangsan");

        //User类的Class对象
        Class<User> cls = User.class;

        testMethod(cls,user);

    }

    //测试方法
    public static void testMethod(Class<User> cls,User user) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method[] methods = cls.getMethods();
        for(Method m:methods){
            System.out.println(m);
        }

        //私有方法
        Method method = cls.getDeclaredMethod("haha",int.class);

        //调用方法
        method.setAccessible(true);
        System.out.println(method.invoke(user,100));;
        System.out.println(method.invoke(null,100));;

        Method m = cls.getMethod("getName");
        System.out.println(m.invoke(user));
    }

    //测试属性
    public static void testField(Class<User> cls,User user) throws NoSuchFieldException, IllegalAccessException {
        Field field = cls.getDeclaredField("name");

        System.out.println(field.getName());
        System.out.println(field.getType());

        //忽略权限
        field.setAccessible(true);

        field.set(user,"zhangsanfeng");

        System.out.println(field.get(user));
    }

}

public java.lang.String com.yjxxt.entity.User.getName()
public java.lang.String com.yjxxt.entity.User.toString()
public void com.yjxxt.entity.User.setName(java.lang.String)
public int com.yjxxt.entity.User.getPwd()
public static void com.yjxxt.entity.User.testStatic()
public void com.yjxxt.entity.User.setPwd(int)
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
haha大笑…100
null
haha大笑…100
null
zhangsan

1.4反射操作数组

反射操作数组
     static Object newInstance(类<?> componentType, int length) 创建具有指定组件类型和长度的新数组。
     static Object get(Object array, int index) 返回指定数组对象中索引组件的值。
     static void set(Object array, int index, Object value) 将指定数组对象的索引组件的值设置为指定的新值。
反射常用方法
public class Class005_Reflect {
    public static void main(String[] args) throws Exception {
        testArray();

        test(String.class);

    }
    public static void test(Class<String> cls){
        //int getModifiers() 返回此类或接口的Java语言修饰符,以整数编码。
        System.out.println(cls.getModifiers());
        System.out.println(Modifier.toString(cls.getModifiers()));

        //类<?>[] getInterfaces() 返回由此对象表示的类或接口直接实现的接口。
        System.out.println(Arrays.toString(cls.getInterfaces()));

        //String getName() 返回此 类对象表示的实体名称(类,接口,数组类,基本类型或void),作为 String 。
        System.out.println(cls.getName());

        //String getSimpleName() 返回源代码中给出的基础类的简单名称。
        System.out.println(cls.getSimpleName());
    }

    //简单操作数组
    public static void testArray(){
        int[] arr = (int[]) Array.newInstance(int.class,5);

        Array.set(arr,2,200);

        System.out.println(Arrays.toString(arr));

        System.out.println(Array.get(arr,2));
    }
}

[0, 0, 200, 0, 0]
200
17
public final
[interface java.io.Serializable, interface java.lang.Comparable, interface java.lang.CharSequence]
java.lang.String
String

2.注解

2.1注解概述

注解 : Annotation
    标注

    java8引入的注解机制

作用:
     1.注释
     2.标志|标识
     3.使用注解时可以传递参数,可以在程序中通过反射操作注解,获取配置的信息在程序中使用
     4.可以存在于Class文件中
     5.大量的代替|简化配置文件的使用

使用:
    @注解名(参数)

注解的分类:
    jdk的内置注解 : 常见
        @Override 检查重写方法
        @SuppressWarnings("all") 抑制警告
        @Deprecated 表示已过时,不推荐使用
        @FunctionalInterface 标识函数式接口

    参数的个数分类:
            标志|标识注解
            单值注解
            完整注解
    元注解 : 注解注解的注解
    自定义注解

2.2元注解

元注解 : 就是负责注解其他注解
    1)@Target 用于描述注解的使用范围
    2)@Retention 规定注解类型的声明周期
    3)@Documented 保留在API文档中
    4)@Inherited 标识注解类型可以被继承

2.3自定义注解

自定义注解
    1.@interface 定义注解类型
    2.默认实现java.lang.annotation.Annotation接口
    3.自定义的注解类型就不能显示的继承其他父类,实现其他接口
    4.如果注解类中的属性只有一个,建议名字为value,为value属性赋值可以直接赋值
    5.为注解类型定义属性|字段: 数据类型 数据名();
    6.属性的数据类型要求为: 基本数据类型 String, 枚举 , 注解类型 , 以及以上类型的数组
    7.属性可以通过default提供默认值
public class Class003_MyAnnotation {
    @MyAnnotation(value=111,haha=123,hehe=321)
    int apple;
}


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    int value() default 1;
    int haha();
    int hehe();
}

2.4注解解析器

注解解析器 : 通过反射操作注解

案例: 自定义水果清单 FruitList
    int apple;
    int pair;

    为每种水果提供一个默认的进货数量,通过注解进行配置

    注解类型: FruitNum  属性: int value();

注意:
    如果通过反射操作注解,注解类型的生命周期应该定义为运行期
public class Class004_FruitList {
    public static void main(String[] args) throws Exception {
        FruitList list = new FruitList();
        list.apple=200;
        System.out.println(list);

        testFruitList(list,FruitList.class);

        System.out.println(list);
    }

    //注解解析器
    public static FruitList testFruitList(FruitList list,Class<FruitList> cls) throws  Exception {
        //1.获取所有属性
        Field[] arr = cls.getDeclaredFields();
        System.out.println(Arrays.toString(arr)+"11111");
        //2.判断当前对象的每一个属性值
        for(Field field:arr){
            Object value =  field.get(list);
            System.out.println(value+"------");
            //是否==null,如果不等于 略过  如果==null 1)获取当前成员变量上的注解对象,  2)获取到实现   3)赋值
            if(value==null){
                //判断当前属性上是否存在FruitNum注解修饰
                if(field.isAnnotationPresent(FruitNum.class)){
                    //获取当前属性上的FruitNum注解实例
                    FruitNum fruitNum = field.getAnnotation(FruitNum.class);
                    System.out.println(fruitNum.value()+"+++");

                    //为当前属性赋值,值为成员上的注解上配置的实参
                    field.set(list,fruitNum.value());
                }
            }
        }

        return list;
    }
}

class FruitList{
    @FruitNum(50)
    Integer apple;
    @FruitNum
    Integer pair;

    @Override
    public String toString() {
        return "FruitList{" +
                "apple=" + apple +
                ", pair=" + pair +
                '}';
    }
}

//水果数量
@Retention(RetentionPolicy.RUNTIME)// 如果通过反射操作注解,注解类型的生命周期应该定义为运行期
@interface FruitNum{
    int value() default 20;
}

FruitList{apple=200, pair=null}
[java.lang.Integer com.yjxxt.annotation.FruitList.apple, java.lang.Integer com.yjxxt.annotation.FruitList.pair]11111
200------
null------
20+++
FruitList{apple=200, pair=20}

3.java8新特性

函数式接口
    接口中只与一个必须被重写的抽象方法
    @FunctionalInterface

四大内置函数式接口:
    1.消费型接口  Consumer<T>
        void accept(T t)   --> 有来无回,有参数没有返回值
    2.供给型接口  Supplier<T>
        T get()
    3.函数型接口  Function<T,R>
        R apply(T t)
    4.段言型接口  Predicate<T>
        boolean test(T t)
public class Class001_FunctionalInterface {
    public static void main(String[] args) {
        testConsumer(5000, m-> System.out.println("今天在薇娅直播间为鸿星尔克消费"+m));
        testConsumer(10000, m-> System.out.println("今天在李佳琪直播间为鸿星尔克消费"+m));

        System.out.println(getNum(5,()->(int)(Math.random()*(5-1+1)+1)));;
        System.out.println(getNum(3,()->(int)(Math.random()*(15-10+1)+10)));;

        System.out.println(strHandler("   haha  ",s->s.trim()));;
        System.out.println(strHandler("   haha  ",s->s.toUpperCase()));;

        List<Employee> list = new ArrayList<Employee>();

        list.add(new Employee(1003,"zhangsan",19));
        list.add(new Employee(1002,"lisi",17));
        list.add(new Employee(1001,"wangwu",18));

        System.out.println(checkEmp(list,e->e.getAge()>=18));
    }

    //对员工集合中的员工数据按照某种规则进行过滤,返回结果
    public static List<Employee> checkEmp(List<Employee> list, Predicate<Employee> predicate){
        List<Employee> newList = new ArrayList<>();
        for(Employee e:list){
            if(predicate.test(e)){
                newList.add(e);
            }
        }
        return newList;
    }

    //对字符串进行处理,返回结果
    public static String strHandler(String str, Function<String,String> my){
        return my.apply(str);
    }

    //产生指定个数的指定规则的随机数
    public static List<Integer> getNum(int num, Supplier<Integer> supplier){
        List<Integer> list = new ArrayList<>();
        for(int i=1;i<=num;i++){
            list.add(supplier.get());
        }
        return list;
    }

    //消费的功能
    public static void testConsumer(int money, Consumer<Integer> con){
        con.accept(money);
    }
}

今天在薇娅直播间为鸿星尔克消费5000
今天在李佳琪直播间为鸿星尔克消费10000
[5, 2, 5, 3, 5]
[12, 12, 10]
haha
HAHA
[Employee [id=1003, name=zhangsan, age=19], Employee [id=1001, name=wangwu, age=18]]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值