文章目录
- 1. 反射
- 1.1 反射演示
- 1.2 反射原理
- 2. Class类
- 3. 注解
- 3.1 内置注解
- 3.2 元注解
- 3.3 自定义注解
- 4. lambda表达式
- 5. lambda精简
- 6. lambda调用方法
1. 反射
1.1 反射演示
有一个猫类,如下:
public class Cat {private String name;private int age;public void speak(){System.out.println("猫不会说话");}public void climb(){System.out.println("猫会爬");}public Cat() {}public Cat(String name, int age) {this.name = name;this.age = age;}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;}
}
假设我们配置属性文件re.properties:
className=Cat
methodName=speak
编写反射的主方法,首先先读取配置文件,然后根据配置文件写的类路径、类方法来获取类:
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;public class tmp {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException {
// 读取配置文件Properties properties = new Properties();properties.load(new FileInputStream("re.properties"));
// 加载配置文件中的属性String className = properties.getProperty("className");String methodName = properties.getProperty("methodName");Class cls = Class.forName(className); // 根据类的路径获取类Object obj = cls.newInstance(); // 获取这个类的实例Method method = cls.getMethod(methodName); // 获取类里面的方法method.invoke(obj); // 调用类里面的方法}
}
根据目前的位置,输出是:
猫不会说话
反射的作用是,如果我们修改配置文件里面的方法名为climb
,则可以使得输出为:
猫会爬
这样就可以使得我们只修改配置文件而无需修改源码,实现代码功能的改变。
1.2 反射原理
.java文件经过编译器编译后变成了.class字节码文件,.class文件里面编译了.java文件里面的所有东西,有类、属性、方法、构造方法等。
Java程序的加载就是加载.class文件,.class文件被加载进内存后,内存里边有一个.class文件对应的内存区域,内存中包含了.class文件中所有与.java对应的类、属性、方法、构造方法等
通过内存区域内的这些对应的东西进行反射加载,获得具体的类、方法等。
2. Class类
Class.forName(classPath)
加载出来的两个结果属于同一个对象,HashCode相等
3. 注解
3.1 内置注解
@SuppressWarnings("all")
可以注释在类、方法等上表示抑制编译器的所有类型警告,unchecked
表示抑制单类型的警告,unchecked,rawtypes
表示抑制多类型的警告
@Override
是重载方法,比如用在toString()
方法上
@Deprecated
表示是一个过时的方法,不推荐使用,当使用这个方法时,方法上会被标记一个删除线
3.2 元注解
@Target
表示在哪些位置上标记注解:@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.PARAMETER...})
@Retention
:指定注解的声明周期,如:@Retention(RetentionPolicy.RUNTIME)
@Document
:会在JavaDoc里出现
3.3 自定义注解
自定义注解的代码,使用元注解:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NodeU{
}
4. lambda表达式
通过lambda表达式自定义实现接口的方法,并调用打印结果
public class tmp {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException {Dog d = (int a, int b) -> {return a + b;};System.out.println(d.add(3, 2));}
}interface Dog{int add(int a, int b);
}
如果interface里面有多个方法:
interface Dog{int add(int a, int b);int sub(int a, int b); // 二义性int mul(int a, int b); // 二义性
}
则主方法里的写法就会有问题,因为(int a, int b)不知道具体指的是哪个。
5. lambda精简
void方法可以精简成:
public class tmp {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException {Dog d = () -> System.out.println("aaa");d.add();}
}interface Dog{void add();
}
精简4中的代码:
public class tmp {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException {Dog d = (a,b)->(a + b);System.out.println(d.add(3, 2));}
}interface Dog{int add(int a, int b);
}
又如:
public class tmp {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException {Dog d = a-> System.out.println("a" + a);d.add("1");}
}interface Dog{void add(String a);
}
单个参数可以不带括号,但是多个参数必须带括号。这个要求是Dog接口的方法里只有一个含一个参数的方法,否则会报错
-
一个参数时,()可省略
-
方法体只有一条语句时,{}可省略
-
如果方法体是return,那省略同时return也要省略
-
参数类型可以省略(String a)可以直接变为(a)
6. lambda调用方法
大概就是将类tmp中的method方法,作为接口Dog中类似方法的实现(method是以两个int为参数的方法,而Dog中恰好有两个int的方法)
public class tmp {public static void main(String[] args) {tmp _tmp = new tmp();Dog d = _tmp::method;System.out.println(d.add(1, 2));System.out.println(d.add(3, 4));System.out.println(d.add(6, 5));}public int method(int a, int b){return a+b;}
}interface Dog{int add(int a, int b);
}
如果dog中多了一个也是两个int参数的方法,则Dog d = _tmp::met
中就会报错。