Java->反射、枚举以及Lambda表达式

目录

一、反射

1.定义

2.反射相关的类

1.常用获得类的相关方法

2.常用获得类中属性相关的方法

3.获得类中注解相关的方法

4.获得类中构造器相关的方法

5.获得类中方法的相关方法

3.获得class的三种方法 

4.创建对象

5.反射私有的构造方法

6.反射私有属性

7.反射私有方法

8.反射的优缺点

二、枚举

1.枚举的定义

2.枚举的使用

2.1switch语句

2.2常用方法

3.枚举的优缺点

4.枚举和反射

三、Lambda表达式

1.函数式接口

2.Lambda的使用

3.变量捕获

3.1匿名内部类的变量捕获

3.2Lambda的变量捕获

4.Lambda在集合中的应用


一、反射

1.定义

Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制

2.反射相关的类

类名 用途
Class类 代表类的实体,在运行的Java应用程序中表示类和接口
Field类 代表类的成员变量/类的属性
Method类 代表类的方法
Constructor类 代表类的构造方法

class类代表类的实体,在运行的Java应用程序中表示类和接口

Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为一个对象,这个对象就是 java.lang.Class .这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类 

1.常用获得类的相关方法
方法 用途
getClassLoader() 获得类的加载器
getDeclaredClasses() 返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有的)
forName(String className) 根据类名返回类的对象
newInstance() 创建类的实例
getName() 获得类的完整路径名字
2.常用获得类中属性相关的方法
方法 用途
getField(String name) 获得某个公有的属性对象
getFields() 获得所有公有的属性对象
getDeclaredField(String name) 获得某个属性对象
getDeclaredFields() 获得所有属性对象
3.获得类中注解相关的方法
方法 用途
getAnnotation(Class annotationClass) 返回该类中与参数类型匹配的公有注解对象
getAnnotations() 返回该类所有的公有注解对象
getDeclaredAnnotation(Class annotationClass) 返回该类中与参数类型匹配的所有注解对象
getDeclaredAnnotations() 返回该类所有的注解对象
4.获得类中构造器相关的方法
方法 用途
getConstructor(Class... parameterTypes) 获得该类中与参数类型匹配的公有构造方法
getConstructors() 获得该类的所有公有构造方法
getDeclaredConstructor(Class... parameterTypes) 获得该类中与参数类型匹配的构造方法
getDeclaredConstructors() 获得该类所有构造方法
5.获得类中方法的相关方法
方法 用途
getMethod(String name, Class... parameterTypes) 获得该类某个公有的方法
getMethods() 获得该类所有公有的方法
getDeclaredMethod(String name, Class... parameterTypes) 获得该类某个方法
getDeclaredMethods() 获得该类所有方法

3.获得class的三种方法 

第一种,使用 Class.forName("类的全路径名"); 静态方法。
前提:已明确类的全路径名。
第二种,使用 .class 方法。
说明:仅适合在编译前就已经明确要操作的 Class
第三种,使用类对象的 getClass() 方法

public class Text {
    public static void main(String[] args) throws ClassNotFoundException {
        Class c1 = Class.forName("dome1.Student");

        Class c2 = Student.class;

        Student student = new Student();
        Class c3 = student.getClass();

        System.out.println(c1.equals(c2));
        System.out.println(c1.equals(c3));
        System.out.println(c3.equals(c2));
    }
}


package dome1;

import java.util.Objects;

public class Student {
    private String name = "bit";
    //公有属性age
    public int age = 18;
    //不带参数的构造方法
    public Student(){
        System.out.println("Student()");
    }
    private Student(String name,int age) {
        this.name = name;
        this.age = age;
        System.out.println("Student(String,name)");
    }
    private void eat(){
        System.out.println("i am eat");
    }
    public void sleep(){
        System.out.println("i am pig");
    }
    private void function(String str) {
        System.out.println(str);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
//Student()
//true
//true
//true

4.创建对象

public class Text {
    public static void main(String[] args) {
        try {
            Class c1 = Class.forName("dome1.Student");
            Student student =(Student)c1.newInstance();
            System.out.println(student);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}
//Student()
//Student{name='bit', age=18}

5.反射私有的构造方法

public class Text {
    public static void main(String[] args) {
        reflectPrivateConstructor();
    }

    public static void reflectPrivateConstructor() {
        try {
            Class c1 = Class.forName("dome1.Student");
            Constructor declaredConstructor
                    = c1.getDeclaredConstructor(String.class, int.class);
            declaredConstructor.setAccessible(true);  //允许调用私有构造方法
            Student student = (Student)declaredConstructor.newInstance("zhangsan",10);
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}
//Student(String,name)
//Student{name='zhangsan', age=10}

6.反射私有属性

public class Text {
    public static void main(String[] args) {
        reflectPrivateField();
    }

    public static void reflectPrivateField() {
        try {
            Class c1 = Class.forName("dome1.Student");
            Field field = c1.getDeclaredField("name");
            field.setAccessible(true);
            Student student = (Student)c1.newInstance();
            field.set(student,"诸葛亮");
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}
//Student()
//Student{name='诸葛亮', age=18}

7.反射私有方法

public class Text {
    public static void main(String[] args) {
        reflectPrivateMethod();
    }

    public static void reflectPrivateMethod() {
        try {
            Class c1 = Class.forName("dome1.Student");
            Method me = c1.getDeclaredMethod("function", String.class);
            me.setAccessible(true);
            Student student = (Student)c1.newInstance();
            me.invoke(student,"我是参数!");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
}
//Student()
//我是参数!

8.反射的优缺点

优点:
1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
3. 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。
缺点:
1. 使用反射会有效率问题。会导致程序效率降低。
2. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂

二、枚举

1.枚举的定义

public enum TextEnum {
    RED,WHITE,GREEN,BLACK;
}

2.枚举的使用

2.1switch语句
public enum TestEnum {
    RED,WHITE,GREEN,BLACK;

    public static void main(String[] args) {
        TestEnum textEnum = TestEnum.BLACK;
        switch(textEnum) {
            case RED :
                System.out.println("RED");
                break;
            case WHITE:
                System.out.println("WHITE");
                break;
            case GREEN:
                System.out.println("GREEN");
                break;
            case BLACK:
                System.out.println("BLACK");
                break;
            default:
                System.out.println("颜色不匹配!");
        }
    }
}
//BLACK
2.2常用方法
方法名称 描述
values() 以数组形式返回枚举类型的所有成员
ordinal() 获取枚举成员的索引位置
valueOf() 将普通字符串转换为枚举实例
compareTo() 比较两个枚举成员在定义时的顺序
public enum TestEnum {
    RED,WHITE,GREEN,BLACK;

    public static void main(String[] args) {
        TestEnum[] values = TestEnum.values();
        for (int i = 0; i < values.length; i++) {
            System.out.print(values[i] + " ");
        }
        System.out.println();
    }
}
//RED WHITE GREEN BLACK 
public enum TestEnum {
    RED,WHITE,GREEN,BLACK;

    public static void main(String[] args) {
        TestEnum[] values = TestEnum.values();
        for (int i = 0; i < values.length; i++) {
            System.out.print(values[i] + " " +  values[i].ordinal() + " ");
        }
        System.out.println();
    }
}

//RED 0 WHITE 1 GREEN 2 BLACK 3 
public enum TestEnum {
    RED,WHITE,GREEN,BLACK;

    public static void main(String[] args) {
        TestEnum testEnum = TestEnum.valueOf("GREEN");
        System.out.println(testEnum);
//        TestEnum testEnum = TestEnum.valueOf("GREEN2"); error
    }
}
//GREEN

 后面定义的比前面的大

public enum TestEnum {
    RED,WHITE,GREEN,BLACK;

    public static void main(String[] args) {
        System.out.println(RED.compareTo(GREEN));
    }
}
//-2

自定义的枚举类 默认继承于Enum这个类

Enum这个类 默认是一个抽象类

枚举的构造方法默认是私有的 不能被继承

public enum TestEnum {
//    RED,WHITE,GREEN,BLACK;
    
    RED(1,"red"),WHITE(2,"white"),
    GREEN(3,"green"),black(4,"black");
    
    private int ordinal;
    private String color;

    TestEnum(int ordinal, String color) {
        this.ordinal = ordinal;
        this.color = color;
    }
}

3.枚举的优缺点

优点:
1. 枚举常量更简单安全 。
2. 枚举具有内置方法 ,代码更优雅
缺点:
1. 不可继承,无法扩展

4.枚举和反射

package dome2;

public enum TestEnum {
//    RED,WHITE,GREEN,BLACK;

    RED(1,"red"),WHITE(2,"white"),
    GREEN(3,"green"),black(4,"black");

    private int ordinal;
    private String color;

    TestEnum(int ordinal, String color) {
        this.ordinal = ordinal;
        this.color = color;
    }
}

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test {
    public static void main(String[] args) {
        try {
            Class c = Class.forName("dome2.TestEnum");
            Constructor declaredConstructor =
//            c.getDeclaredConstructor(int.class, String.class);
            c.getDeclaredConstructor(String.class,int.class,int.class, String.class);
            declaredConstructor.setAccessible(true);
            TestEnum testEnum = (TestEnum) declaredConstructor.newInstance(5,"橙色");
            System.out.println(testEnum);

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

//异常

不能通过反射来创建枚举对象 

三、Lambda表达式

1.函数式接口

1. 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口
2. 如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的

@FunctionalInterface
public interface NoParameterNoReturn {
    void test();
    default void func() {
        
    }
    static void func2() {
        
    }
}

2.Lambda的使用

//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn {
    void test();
}
//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn {
    void test(int a);
}
//无返回值多个参数
@FunctionalInterface
interface MoreParameterNoReturn {
    void test(int a,int b);
}




//有返回值无参数
@FunctionalInterface
interface NoParameterReturn {
    int test();
}
//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn {
    int test(int a);
}
//有返回值多参数
@FunctionalInterface
interface MoreParameterReturn {
    int test(int a,int b);
}
public class Test {
//无参无返回值

    public static void main(String[] args) {
        NoParameterNoReturn noParameterNoReturn = ()->{System.out.println("test()...");};
//        NoParameterNoReturn noParameterNoReturn = ()->System.out.println("test()...");
        noParameterNoReturn.test();;
    }
    public static void main1(String[] args) {
        //相当于一个匿名内部类  实现了接口并且实现了接口的方法
        NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {
            @Override
            public void test() {
                System.out.println("test()...");
            }
        };
        noParameterNoReturn.test();
    }
}
public class Test {
//一个参数无返回值

    public static void main(String[] args) {
        OneParameterNoReturn oneParameterNoReturn = (int x)->{System.out.println(x);};
//        OneParameterNoReturn oneParameterNoReturn = x -> System.out.println(x);
        oneParameterNoReturn.test(10);
    }
}
public class Test {
//两个参数 无返回值

    public static void main(String[] args) {
        MoreParameterNoReturn moreParameterNoReturn = (int x,int y)->{System.out.println(x+y);};
//        MoreParameterNoReturn moreParameterNoReturn = (x,y) -> System.out.println(x+y);
        moreParameterNoReturn.test(1,2);
    }
}
public class Test {
//有返回值 无参数

    public static void main(String[] args) {
        NoParameterReturn noParameterReturn = () -> {return 10;};
//        NoParameterReturn noParameterReturn = () -> 10;
        System.out.println(noParameterReturn.test()); //10
    }
}
public class Test {
//有返回值 一个参数

    public static void main(String[] args) {
        OneParameterReturn oneParameterReturn = x -> x+10;
        System.out.println(oneParameterReturn.test(10)); //20
    }
}
public class Test {
//有返回值 两个参数

    public static void main(String[] args) {
        MoreParameterReturn moreParameterReturn = (x,y) -> x+y;
        System.out.println(moreParameterReturn.test(10, 20));  // 30
    }
}

1. 参数类型可以省略,如果需要省略,每个参数的类型都要省略。
2. 参数的小括号里面只有一个参数,那么小括号可以省略
3. 如果方法体当中只有一句代码,那么大括号可以省略
4. 如果方法体中只有一条语句,且是return语句,那么大括号可以省略,且去掉return关键字。

public class Test {
    public static void main(String[] args) {
        PriorityQueue priorityQueue = new PriorityQueue<>(new Comparator() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        });
        
        PriorityQueue priorityQueue2 = new PriorityQueue<>((o1, o2) -> {return o1.compareTo(o2);});
//        PriorityQueue priorityQueue2 = new PriorityQueue<>((o1, o2) -> o1.compareTo(o2));
    } 
}

3.变量捕获

3.1匿名内部类的变量捕获
class Test {
    public void func(){
        System.out.println("func()");
    }
}
public class TestDemo {
    public static void main(String[] args) {
        int a = 10;
        new Test() {
            @Override
            public void func() {
                //a = 99; error 
                System.out.println("我是内部类,且重写了func这个方法!");
                System.out.println("我是捕获到变量 a == " + a
                        + " 我是一个常量,或者是一个没有改变过值的变量!");
            }
        };
    }
}
3.2Lambda的变量捕获
@FunctionalInterface
interface NoParameterNoReturn {
    void test();
}

class Test {
    public static void main(String[] args) {
        int a = 10;
        NoParameterNoReturn noParameterNoReturn = () -> {
            // a = 99; error
            System.out.println("捕获变量:" + a);
        };
        noParameterNoReturn.test();
    }
}

 Lambda表达式中的this引用是他所在对象的实例

4.Lambda在集合中的应用

对应的接
新增的方法
Collection removeIf() spliterator() stream() parallelStream() forEach()
List replaceAll() sort()
Map getOrDefault() forEach() replaceAll() putIfAbsent() remove() replace() computeIfAbsent()
computeIfPresent() compute() merge()
import java.util.ArrayList;
import java.util.function.Consumer;

public class Test {
    public static void main(String[] args) {
        ArrayList list = new ArrayList<>();
        list.add("hello");
        list.add("abcd");
        list.add("world");
        list.add("feifei");
        list.forEach(new Consumer() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });

        System.out.println("=======");

        list.forEach(s -> System.out.println(s));

        System.out.println("====排序====");

//        list.sort(new Comparator() {
//            @Override
//            public int compare(String o1, String o2) {
//                return o1.compareTo(o2);
//            }
//        });
//        System.out.println("========");
        list.sort((o1,o2) -> o1.compareTo(o2));
        list.forEach(s -> System.out.println(s));
    }
}
//hello
//abcd
//world
//feifei
//=======
//hello
//abcd
//world
//feifei
//====排序====
//abcd
//feifei
//hello
//world
public class Test {
    public static void main(String[] args) {
        Map map = new HashMap<>();
        map.put("hello",1);
        map.put("abcd",8);
        map.put("world",4);
        map.put("feifei",2);

        map.forEach(new BiConsumer() {
            @Override
            public void accept(String s, Integer integer) {
                System.out.print("key: " + s);
                System.out.println("  val: " + integer);
            }
        });

        System.out.println("=====");

        map.forEach((key,val) -> System.out.println("key: " + key + " val: " + val));
    }
}
//key: world  val: 4
//key: hello  val: 1
//key: feifei  val: 2
//key: abcd  val: 8
//=====
//key: world val: 4
//key: hello val: 1
//key: feifei val: 2
//key: abcd val: 8

你可能感兴趣的:(Java数据结构,java,开发语言)