系列文章目录
文章目录
十八、反射机制
1、反射的概念
反射的概述


Java 反射机制研究及应用
反射相关的主要 API
反射的优缺点
2、理解 Class 类并获取 Class 实例
理解 Class


1.类的加载过程:
程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)。
接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此运行时类,就作为Class的一个实例。
2.换句话说,CLass的实例就对应着一个运行时类。
3.加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式来获取此运行时类。
package Test_2.reflectiontest;
public class Person {
private String name;
public int age;
public Person() {
}
private Person(String name){
this.name = name;
}
public Person(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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void show(){
System.out.println("你好,我是一个人");
}
private String showNation(String nation){
System.out.println("我的国籍是:" + nation);
return nation;
}
}
//反射之前,对Person的操作
@Test
public void test1(){
//1、创建Person类的对象
Person p1 = new Person("Tom", 12);
//通过对象,调用其内部的属性方法
p1.age = 10;
System.out.println(p1.toString());
p1.show();
//在Person类外部,不可以通过Person类的对象调用其内部私有结构;
//比如:name,showNation()以及私有的构造器
}
//反射之后,对Person的操作
@Test
public void test2() throws Exception {
Class clazz = Person.class;
//通过反射,创建Person类的对象
Constructor cons = clazz.getConstructor(String.class,int.class);
Object obj = cons.newInstance("Tom", 12);
Person p = (Person) obj;
System.out.println(p.toString());
//通过反射,调用对象指定的属性、方法
//调用属性
Field age = clazz.getDeclaredField("age");
age.set(p,10);
System.out.println(p.toString());
//调用方法
Method show = clazz.getDeclaredMethod("show");
show.invoke(p);
//通过反射,可以调用Person类的私有结构;
//调用私有构造器
Constructor cons1 = clazz.getDeclaredConstructor(String.class);
cons1.setAccessible(true);
Person p1 = (Person) cons1.newInstance("Jerry");
System.out.println(p1);
//调用私有属性
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(p1, "lilei");
System.out.println(p1);
//调用私有方法
Method showNation = clazz.getDeclaredMethod("showNation", String.class);
showNation.setAccessible(true);
String nation = (String) showNation.invoke(p1, "中国");
System.out.println(nation);
}
获取 Class 类的实例(四种方法)
//获取class实例的方法
@Test
public void test3() throws ClassNotFoundException {
//方式一:调用运行时类的属性:.class
Class clazz1 = Person.class;
System.out.println(clazz1);
//方式二:通过运行时类的对象,调用getClass()
Person p1 = new Person();
Class clazz2 = p1.getClass();
System.out.println(clazz2);
//方式三:调用Class的静态方法:forName(String classPath)
Class clazz3 = Class.forName("Test_2.reflectiontest.Person");
System.out.println(clazz3);
System.out.println(clazz1 == clazz2);
System.out.println(clazz1 == clazz3);
//方式四:使用类的加载器:ClassLoader
ClassLoader classLoader = ReflectionTest.class.getClassLoader();
Class clazz4 = classLoader.loadClass("Test_2.reflectiontest.Person");
System.out.println(clazz4);
System.out.println(clazz1 == clazz4);
}
哪些类型可以有 Class 对象
Class c1 = Object.class;
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = int[][].class;
Class c5 = ElementType.class;
Class c6 = Override.class;
Class c7 = int.class;
Class c8 = void.class;
Class c9 = Class.class;
int[] a = new int[10];
int[] b = new int[100];
Class c10 = a.getClass();
Class c11 = b.getClass();
// 只要元素类型与维度一样,就是同一个 Class
System.out.println(c10 == c11);
Class 类的常用方法
| 方法名 | 功能说明 |
| static Class forName(String name) | 返回指定类名 name 的 Class 对象 |
| Object newInstance() |
调用缺省构造函数,返回该 Class 对象的一个实例
|
| getName() |
返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称
|
| Class getSuperClass() | 返回当前 Class 对象的父类的 Class 对象 |
|
Class [] getInterfaces()
| 获取当前 Class 对象的接口 |
|
ClassLoader getClassLoader()
|
返回该类的类加载器
|
| Class getSuperclass() | 返回表示此 Class 所表示的实体的超类的Class |
|
Constructor[] getConstructors()
|
返回一个包含某些 Constructor 对象的数组
|
| Field[] getDeclaredFields() | 返回 Field 对象的一个数组 |
|
Method getMethod(String
name,Class … paramTypes)
|
返回一个 Method 对象,此对象的形参类型为 paramType
|
3、类的加载与 ClassLoader 的理解
类的生命周期
类的加载过程

类加载器(classloader)

@Test
public void test1(){
//对于自定义类,使用系统类加载器进行加载
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
System.out.println(classLoader);
//调用系统类加载器的getParent():获取扩展类加载器
ClassLoader classLoader1 = classLoader.getParent();
System.out.println(classLoader1);
//调用扩展类加载器的getParent():无法获取引导类加载器
//引导类加载器 主要负责java的核心库类,无法加载自定义类
ClassLoader classLoader2 = classLoader1.getParent();
System.out.println(classLoader2);
}
查看某个类的类加载器对象
@Test
public void test2() throws Exception {
Properties pros = new Properties();
//此时的文件默认在当前的module下。
//读取配置文件的方式一:
//FileInputStream fis = new FileInputStream("jdbc.properties");
//pros.load(fis);
//读取配置文件的方式二:使用ClassLoader
//配置文件默认识别为:当前module的src下
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("jdbc1.properties");
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
System.out.println("user = " + user + ", password = " + password);
}
4、反射的基本应用
应用 1:创建运行时类的对象
@Test
public void test1() throws Exception {
Class<Person> clazz = Person.class;
Object obj = clazz.newInstance();
System.out.println(obj);
Class<?> clazz1 = Class.forName("Test_2.reflectiontest.Person");
Object obj1 = clazz1.newInstance();
System.out.println(obj1);
Class<?> clazz2 = Class.forName("Test_2.reflectiontest.Person");
Constructor<?> constructor = clazz2.getConstructor(String.class,int.class);
Object obj2 = constructor.newInstance("王五",12);
System.out.println(obj2);
}
应用 2:获取运行时类的完整结构
获取运行时类的属性结构及其内部结构
public class FieldTest {
@Test
public void test1(){
Class clazz = Person.class;
//获取属性结构
//getFields():获取当前运行时类及其父类中声明为public访问权限的属性
Field[] fields = clazz.getFields();
for(Field f : fields){
System.out.println(f);
}
System.out.println("-----------");
//getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)
Field[] declaredFields = clazz.getDeclaredFields();
for(Field f1 : declaredFields){
System.out.println(f1);
}
}
//权限修饰符 数据类型 变量名
@Test
public void test2(){
Class clazz = Person.class;
Field[] declaredFields = clazz.getDeclaredFields();
for(Field f : declaredFields){
//System.out.println(f);
//1.权限修饰符
int modifiers = f.getModifiers();
//System.out.println(modifiers);
System.out.print(Modifier.toString(modifiers) + "\t");
//2.数据类型
Class type = f.getType();
System.out.print(type.getName() + "\t");
//3.变量名
String fName = f.getName();
System.out.println(fName);
System.out.println();
}
}
}
获取运行时类的方法结构及其内部结构
public class MethodTest {
//获取运行时类的方法结构
@Test
public void test1(){
Class clazz = Person.class;
//getMethods():获取当前运行时类及其所有父类中声明为public权限的方法
Method[] methods = clazz.getMethods();
for(Method m : methods){
System.out.println(m);
}
System.out.println();
//getDeclaredMethods():获取当前运行时类中声明的所有方法。(不包含父类中声明的方法
Method[] declaredMethods = clazz.getDeclaredMethods();
for(Method m : declaredMethods){
System.out.println(m);
}
}
//获取运行时类的方法的内部结构
@Test
public void test2(){
Class clazz = Person.class;
Method[] declaredMethods = clazz.getDeclaredMethods();
for(Method m : declaredMethods){
//1.获取方法声明的注解
Annotation[] annotations = m.getAnnotations();
for(Annotation a : annotations){
System.out.println(a);
}
//2.权限修饰符
System.out.print(Modifier.toString(m.getModifiers()) + "\t");
//3.返回值类型
System.out.print(m.getReturnType().getName() + "\t");
//4.方法名
System.out.print(m.getName());
//5.形参列表
System.out.print("(");
Class[] parameterTypes = m.getParameterTypes();
if(!(parameterTypes == null && parameterTypes.length == 0)){
for(int i = 0; i < parameterTypes.length; i++){
if(i == parameterTypes.length -1){
System.out.print(parameterTypes[i].getName() + "arg_" + i);
break;
}
System.out.print(parameterTypes[i].getName() + "arg_" + i + ", ");
}
}
System.out.print(")");
//6.抛出的异常
Class[] exceptionTypes = m.getExceptionTypes();
if(exceptionTypes.length > 0){
System.out.print("throws");
for(int i = 0; i < exceptionTypes.length; i++){
if( i == exceptionTypes.length -1){
System.out.print(exceptionTypes[i].getName());
break;
}
System.out.print(exceptionTypes[i].getName() + ", ");
}
}
System.out.println();
}
}
}
public class OtherTest {
//获取构造器结构
@Test
public void test1(){
Class clazz = Person.class;
//getConstructors():获取当前运行时类中声明为public的构造器
Constructor[] constructors = clazz.getConstructors();
for(Constructor c : constructors){
System.out.println(c);
}
System.out.println();
//getDeclaredConstructors():获取当前运行时类中声明的所以构造器
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for(Constructor c : declaredConstructors){
System.out.println(c);
}
}
//获取运行时类的父类及父类的泛型
@Test
public void test2(){
Class clazz = Person.class;
//获取运行时类的父类
Class superclass = clazz.getSuperclass();
System.out.println(superclass);
//获取运行时类的泛型父类
Type genericSuperclass = clazz.getGenericSuperclass();
System.out.println(genericSuperclass);
//获取父类的泛型类型
ParameterizedType paramType = (ParameterizedType) genericSuperclass;
Type[] actualTypeArguments = paramType.getActualTypeArguments();
for(Type t : actualTypeArguments){
System.out.println(t.getTypeName());
}
}
//获取运行时类实现的接口
@Test
public void test3(){
Class clazz = Person.class;
Class[] interfaces = clazz.getInterfaces();
for(Class c : interfaces){
System.out.println(c);
}
System.out.println();
//获取运行时类的父类实现的接口
Class[] interfaces1 = clazz.getSuperclass().getInterfaces();
for(Class c :interfaces1){
System.out.println(c);
}
}
//获取运行时类所在的包
@Test
public void test4(){
Class clazz = Person.class;
Package aPackage = clazz.getPackage();
System.out.println(aPackage);
}
//获取运行时类声明的注解
@Test
public void test5(){
Class clazz = Person.class;
Annotation[] annotations = clazz.getAnnotations();
for (Annotation a : annotations){
System.out.println(a);
}
}
}
应用 3:调用运行时类的指定结构
//调用指定的属性(方法1,不推荐
@Test
public void testField() throws Exception{
Class clazz = Person.class;
//创建运行时类的对象
Person p = (Person) clazz.newInstance();
//获取指定的属性:要求运行时类中的属性声明为public
//通常不采用此方法
Field id = clazz.getField("id");
//设置当前属性值
id.set(p,1001);
//获取当前属性值
int pId = (int) id.get(p);
System.out.println(pId);
}
//调用指定的属性方法2
@Test
public void testField1() throws Exception{
Class clazz = Person.class;
//创建运行时类的对象
Person p = (Person) clazz.newInstance();
//1.getDeclaredField():获取运行时类中指定变量名的属性
Field name = clazz.getDeclaredField("name");
//2.保证当前属性是可访问的
name.setAccessible(true);
//3.获取、设置指定对象的此属性值
name.set(p,"Tom");
System.out.println(name.get(p));
}
//调用指定的方法
@Test
public void testMethod() throws Exception{
Class clazz = Person.class;
//创建运行时类的对象
Person p = (Person) clazz.newInstance();
//getDeclaredMethod():参数1:方法名称;参数2:方法形参列表
Method show = clazz.getDeclaredMethod("show", String.class);
//保证当前属性是可访问的
show.setAccessible(true);
//invoke():参数1:方法的调用者 ; 参数2:给方法形参赋值的实参
Object returnValue = show.invoke(p, "China");
System.out.println(returnValue);
//调用静态方法
Method showDesc = clazz.getDeclaredMethod("showDesc");
showDesc.setAccessible(true);
//以下三个都行
//Object returnValue1 = showDesc.invoke(p);
//Object returnValue1 = showDesc.invoke(Person.class);
Object returnValue1 = showDesc.invoke(null);
System.out.println(returnValue1);
}
调用指定的构造器
//调用指定的构造器
@Test
public void testConstructor() throws Exception{
Class clazz = Person.class;
//1.获取指定构造器
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//2.保证此构造器是可访问的
constructor.setAccessible(true);
//3.调用此构造器创建运行时类的对象
Person p = (Person) constructor.newInstance("Tom");
System.out.println(p.toString());
}
应用4:动态代理
代理设计模式的原理:
使用一个代理将对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
静态代理
interface ClothFactory{
void produceCloth();
}
//代理类
class ProxyClothFactory implements ClothFactory{
private ClothFactory factory; //用被代理类对象进行实例化
public ProxyClothFactory(ClothFactory factory){
this.factory = factory;
}
@Override
public void produceCloth() {
System.out.println("代理工厂做一些准备工作");
factory.produceCloth();
System.out.println("代理工厂做一些后续的收尾工作");
}
}
//被代理类
class NikeClothFactory implements ClothFactory{
@Override
public void produceCloth() {
System.out.println("耐克工厂生产一批运动服");
}
}
public class StaticProxyTest {
public static void main(String[] args) {
//创建被代理类的对象
NikeClothFactory nike = new NikeClothFactory();
//创建代理类的对象
ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nike);
proxyClothFactory.produceCloth();
}
}
动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Human{
String getBrief();
void eat(String food);
}
//被代理类
class SuperMan implements Human{
@Override
public String getBrief() {
return "I can fly!";
}
@Override
public void eat(String food) {
System.out.println("我喜欢吃 " + food);
}
}
class HumanUtil{
public void method1(){
System.out.println("通用方法一");
}
public void method2(){
System.out.println("通用方法二");
}
}
class ProxyFactory{
//调用此方法,返回一个代理类的对象
public static Object getProxyInstance(Object obj){
MyInvocationHandler handler = new MyInvocationHandler();
handler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj; //需要使用被代理类的对象进行赋值
public void bind(Object obj){
this.obj = obj;
}
//当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法:invoke()
//将被代理类要执行的方法a的功能就声明在invoke()中
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
HumanUtil util = new HumanUtil();
util.method1();
//method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
//obj:被代理类对象
Object returnValue = method.invoke(obj, args);
util.method2();
return returnValue;
}
}
public class ProxyTest {
public static void main(String[] args) {
SuperMan superMan = new SuperMan();
//proxyInstance:代理类的对象
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
String brief = proxyInstance.getBrief();
System.out.println(brief);
proxyInstance.eat("汉堡");
System.out.println("----------------------------");
NikeClothFactory nikeClothFactory = new NikeClothFactory();
ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);
proxyClothFactory.produceCloth();
}
}
十九、Java8新特性
1、Lambda 表达式
Lambda 表达式及其语法
Lambda表达式的本质:作为接口的实例
Lambda表达式语法
语法格式一:无参,无返回值
//语法格式一:无参,无返回值
@Test
public void test1(){
//未使用 Lambda 表达式
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("我爱北京天安门");
}
};
r1.run();
System.out.println("***********************");
//使用 Lambda 表达式
Runnable r2 = () -> {
System.out.println("我爱北京故宫");
};
r2.run();
}
语法格式二:Lambda 需要一个参数,但是没有返回值。
@Test
public void test2(){
//未使用 Lambda 表达式
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("谎言和誓言的区别是什么?");
System.out.println("*******************");
//使用 Lambda 表达式
Consumer<String> con1 = (String s) -> {
System.out.println(s);
};
con1.accept("一个是听得人当真了,一个是说的人当真了");
}
语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
//语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断”
@Test
public void test3(){
//语法格式三使用前
Consumer<String> con1 = (String s) -> {
System.out.println(s);
};
con1.accept("一个是听得人当真了,一个是说的人当真了");
System.out.println("*******************");
//语法格式三使用后
Consumer<String> con2 = (s) -> {
System.out.println(s);
};
con2.accept("一个是听得人当真了,一个是说的人当真了");
}
语法格式四:Lambda 若只需要一个参数时,参数的小括号可以省略
//语法格式四:Lambda 若只需要一个参数时,参数的小括号可以省略
@Test
public void test4(){
//语法格式四使用前
Consumer<String> con1 = (s) -> {
System.out.println(s);
};
con1.accept("一个是听得人当真了,一个是说的人当真了");
System.out.println("*******************");
//语法格式四使用后
Consumer<String> con2 = s -> {
System.out.println(s);
};
con2.accept("一个是听得人当真了,一个是说的人当真了");
}
语法格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值
//语法格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值
@Test
public void test5(){
//语法格式五使用前
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
System.out.println(com1.compare(12,21));
System.out.println("*****************************");
//语法格式五使用后
Comparator<Integer> com2 = (o1,o2) -> {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(com2.compare(12,6));
}
语法格式六:当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略
//语法格式六:当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略
@Test
public void test6(){
//语法格式六使用前
Comparator<Integer> com1 = (o1,o2) -> {
return o1.compareTo(o2);
};
System.out.println(com1.compare(12,6));
System.out.println("*****************************");
//语法格式六使用后
Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);
System.out.println(com2.compare(12,21));
}
@Test
public void test7(){
//语法格式六使用前
Consumer<String> con1 = s -> {
System.out.println(s);
};
con1.accept("一个是听得人当真了,一个是说的人当真了");
System.out.println("*****************************");
//语法格式六使用后
Consumer<String> con2 = s -> System.out.println(s);
con2.accept("一个是听得人当真了,一个是说的人当真了");
}

举例:
@Test
public void test() {
//类型推断 1
// ArrayList<String> list = new ArrayList<String>();
ArrayList<String> list = new ArrayList<>();
//类型推断 2
//int[] arr = new int{1, 2, 3};
int[] arr = {1, 2, 3};
}
2、函数式(Functional)接口
什么是函数式接口



Java 内置函数式接口
其他接口

public class LambdaTest2 {
@Test
public void test1(){
happyTime(500, new Consumer<Double>() {
@Override
public void accept(Double aDouble) {
System.out.println("学习太累了,去天上人间买了瓶矿泉水,价格为:" + aDouble);
}
});
System.out.println("---------------");
happyTime(400,money -> System.out.println("学习太累了,去天上人间喝了口水,价格为:" + money));
}
public void happyTime(double money, Consumer<Double> con){
con.accept(money);
}
@Test
public void test2(){
List<String> list = Arrays.asList("北京", "南京", "天津", "东京", "西经", "普京");
List<String> newList = filterString(list, new Predicate<String>() {
@Override
public boolean test(String s) {
return s.contains("京");
}
});
System.out.println(newList);
System.out.println("-----------------");
List<String> newList1 = filterString(list, s -> s.contains("京"));
System.out.println(newList1);
}
public List<String> filterString(List<String> list , Predicate<String> pre){
ArrayList<String> filterList = new ArrayList<>();
for(String s : list){
if(pre.test(s)){
filterList.add(s);
}
}
return filterList;
}
}
3、方法引用与构造器引用
方法引用
public class MethodRefTest {
// 情况一:对象 :: 实例方法
//Consumer 中的 void accept(T t)
//PrintStream 中的 void println(T t)
@Test
public void test1(){
Consumer<String> con1 = str -> System.out.println(str);
con1.accept("北京");
System.out.println("**********************");
PrintStream ps = System.out;
Consumer<String> con2 = ps::println;
con2.accept("beijing");
}
//Supplier 中的 T get()
//Employee 中的 String getName()
@Test
public void test2(){
Employee emp = new Employee("Tom", "海天大厦", 28);
Supplier<String> sup1 = () -> emp.getName();
System.out.println(sup1.get());
System.out.println("*******************");
Supplier<String> sup2 = emp::getName;
System.out.println(sup2.get());
}
// 情况二:类 :: 静态方法
//Comparator 中的 int compare(T t1,T t2)
//Integer 中的 int compare(T t1,T t2)
@Test
public void test3(){
Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1, t2);
System.out.println(com1.compare(12,231));
System.out.println("----------------------");
Comparator<Integer> com2 = Integer::compare;
System.out.println(com2.compare(12,22));
}
//Function 中的 R apply(T t)
//Math 中的 Long round(Double d)
@Test
public void test4(){
Function<Double,Long> func = new Function<Double, Long>() {
@Override
public Long apply(Double aDouble) {
return Math.round(aDouble);
}
};
System.out.println(func.apply(10.5));
Function<Double, Long> func1 = aDouble -> Math.round(aDouble);
System.out.println(func1.apply(12.3));
Function<Double,Long> func2 = Math::round;
System.out.println(func2.apply(15.8));
}
// 情况三:类 :: 实例方法 (有难度)
// Comparator 中的 int comapre(T t1,T t2)
// String 中的 int t1.compareTo(t2)
@Test
public void test5(){
Comparator<String> com1 = (s1, s2) -> s1.compareTo(s2);
System.out.println(com1.compare("abc","abd"));
Comparator<String> com2 = String::compareTo;
System.out.println(com2.compare("abc","abc"));
}
//BiPredicate 中的 boolean test(T t1, T t2);
//String 中的 boolean t1.equals(t2)
@Test
public void test6(){
BiPredicate<String, String> pre1 = (t1, t2) -> t1.equals(t2);
System.out.println(pre1.test("abc","abd"));
BiPredicate<String, String> pre2 = String::equals;
System.out.println(pre2.test("abc","abc"));
}
// Function 中的 R apply(T t)
// Employee 中的 String getName();
@Test
public void test7(){
Employee employee = new Employee("Tom","北京",12);
Function<Employee,String> func = e -> e.getName();
System.out.println(func.apply(employee));
Function<Employee,String> func1 = Employee::getName;
System.out.println(func1.apply(employee));
}
}
构造器引用
public class ConstructorRefTest {
//构造器引用
//Supplier 中的 T get()
//Employee 的空参构造器:Employee()
@Test
public void test1(){
Supplier<Employee> sup = new Supplier<Employee>() {
@Override
public Employee get() {
return new Employee();
}
};
Supplier<Employee> sup1 = () -> new Employee();
System.out.println(sup1.get());
Supplier<Employee> sup2 = Employee::new;
System.out.println(sup2.get());
}
//Function 中的 R apply(T t)
@Test
public void test2(){
Function<Integer, Employee> func1 = age -> new Employee(age);
System.out.println(func1.apply(12));
Function<Integer,Employee> func2 = Employee::new;
System.out.println(func2.apply(10));
}
//BiFunction 中的 R apply(T t,U u)
@Test
public void test3(){
BiFunction<String,Integer,Employee> func1 = (name,age) -> new Employee(name,age);
System.out.println(func1.apply("Tom",18));
BiFunction<String,Integer,Employee> func2 = Employee::new;
System.out.println(func2.apply("Jerry",22));
}
}
数组构造引用
//数组引用
//Function 中的 R apply(T t)
@Test
public void test4(){
Function<Integer, String[]> func1 = length -> new String[length];
System.out.println(Arrays.toString(func1.apply(5)));
Function<Integer,String[]> func2 = String[] :: new;
System.out.println(Arrays.toString(func2.apply(10)));
}
}
4、强大的 Stream API
Stream API 说明
Stream 的操作三个步骤

创建 Stream 实例
@Test
public void test1(){
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();
}
@Test
public void test2(){
String[] arr = {"hello", "world"};
Stream<String> stream = Arrays.stream(arr);
}
@Test
public void test3(){
int[] arr = {1, 2, 3, 4, 5};
IntStream stream = Arrays.stream(arr);
}
@Test
public void test4(){
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
stream.forEach(System.out::println);
}
@Test
public void test5(){
// 迭代
// public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
Stream<Integer> stream = Stream.iterate(0, x -> x + 2);
stream.limit(10).forEach(System.out::println);
// 生成
// public static<T> Stream<T> generate(Supplier<T> s)
Stream<Double> stream1 = Stream.generate(Math::random);
stream1.limit(10).forEach(System.out::println);
}
@Test
public void test1(){
//1、创建 Stream
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
//2、加工处理
//过滤:filter(Predicate p)
//把里面的偶数拿出来
/*
* filter(Predicate p)
* Predicate 是函数式接口,抽象方法:boolean test(T t)
*/
stream = stream.filter(t -> t % 2 == 0);
//3、终结操作:例如:遍历
stream.forEach(System.out::println);
}
@Test
public void test2(){
Stream.of(1, 2, 3, 4, 5, 6).filter(t -> t%2==0).forEach(System.out::println);
}
@Test
public void test3(){
Stream.of(1,2,2,3,4,4,5,5,5,6).distinct().forEach(System.out::println);
}
@Test
public void test4(){
Stream.of(1,2,2,3,4,4,5,5,5,6).limit(3).forEach(System.out::println);
}
@Test
public void test5(){
Stream.of(1,2,2,3,4,4,5,5,5,6).skip(3).forEach(System.out::println);
}
2-映 射

@Test
public void test6(){
Stream.of(1, 2, 3, 4, 5, 6).map(t -> t += 1).forEach(System.out::println);
}
@Test
public void test7(){
String[] arr = {"hello", "world", "java"};
Arrays.stream(arr).map(t -> t.toUpperCase()).forEach(System.out::println);
}
@Test
public void test8(){
String[] arr = {"hello", "world", "java"};
Arrays.stream(arr).flatMap(t -> Stream.of(t.split("|"))).forEach(System.out::println);
}
3-排序

@Test
public void test9(){
Stream.of(11, 2, 39, 4, 54, 6, 2, 22, 3, 3, 4, 54, 54).distinct().sorted((t1, t2) -> Integer.compare(t1, t2)).forEach(System.out::println);
}
@Test
public void test1(){
Stream.of(1,2,3,4,5,6).forEach(System.out::println);
}
@Test
public void test2(){
long count = Stream.of(1,2,3,4,5).count();
System.out.println("count:" + count);
}
@Test
public void test3(){
boolean result = Stream.of(2, 4, 6, 8, 9).allMatch(t -> t % 2 == 0);
System.out.println(result);
}
@Test
public void test4(){
boolean result = Stream.of(2, 4, 6, 8, 9).anyMatch(t -> t % 2 == 0);
System.out.println(result);
}
@Test
public void test5(){
Optional<Integer> opt = Stream.of(1,2,3,4,5,6).findFirst();
System.out.println(opt);
}
@Test
public void test6(){
Optional<Integer> opt = Stream.of(1,2,3,4,5,6,7).filter(t->t%3==0).findFirst();
System.out.println(opt);
}
@Test
public void test07(){
Optional<Integer> opt = Stream.of(1,2,4,5,7,8)
.filter(t -> t%3==0)
.findFirst();
System.out.println(opt);
}
@Test
public void test8(){
Optional<Integer> max = Stream.of(1, 2, 3, 4, 5, 6).max((t1, t2) -> Integer.compare(t1, t2));
System.out.println(max);
}

@Test
public void test9(){
Integer reduce = Stream.of(1,2,3,4).reduce(5,(t1,t2)->t1+t2);
System.out.println(reduce);
}
@Test
public void test10(){
Optional<Integer> max = Stream.of(2, 8, 4, 19, 12).reduce((t1, t2) -> t1 > t2 ? t1 : t2);
System.out.println(max);
}
3-收集


@Test
public void test11(){
List<Integer> list = Stream.of(1,2,4,5,7,8)
.filter(t -> t%2==0)
.collect(Collectors.toList());
System.out.println(list);
}
optional类
到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。
Optional<T>类(java.util.Optional)是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用null表示一个值不存在,现在 Optional可以更好的表达这个概念。并且可以避免空指针异常。
Optional类的Javadoc描述如下:这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
1万+



被折叠的 条评论
为什么被折叠?



