java基础之jdk8新特性及java web准备(含反射部分)

经过一段时间,java的学习,明显感到就是一个用的过程,与嵌入式开发明显的不同。嵌入式一些虽然也有库,但大部分的开发过程都是根据实际的芯片手册来写一些底层的驱动,其次才是构建在OS基础上的开发。如果说嵌入式开发也是盖楼的话,那么还要有一个造砖的过程,而java开发主要是往框架里填砖的过程。

常用函数式接口:有且只有一个抽象方法的接口

java中函数式编程的体现就是Lambda.只有确保接口中有且只有一个抽象方法,java中的Lambda才能顺利推导。

注:“语法糖”是指使用更加方便,但是原理不变的代码语法。例如在遍历集合时使用的for-each语法,其实底层的实现原理仍然是迭代器,这便是“语法糖”。从应用层面来讲,Java中的Lambda可以被当做是匿名内部类的“语法糖”,但是二者在原理上是不同的。

格式:

修饰符 interface 接口名称 {
public abstract 返回值类型 方法名称(可选参数信息);
// 其他非抽象方法内容
}
@FunctionalInterface 函数式接口注解

作用:与 @Override 注解一样,检测接口是否是一个函数式接口

           是,编译成功

          否,编译失败,(接口中没有抽象方法,抽象方法的个数多于1个)

函数式接口的使用:一般作为方法的参数和返回值使用。

Lambda特点:延时加载。

使用Lambda表达式作为参数传递,仅仅是把参数传递到showLog方法中,只有满足条件,才会调用接口中的方法。如果条件不满足,不会调用接口中的方法

 

常用的函数式接口:java.util.function包下

Supplier接口:生产数据

java.util.function.Supplier<T>接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对象数据。

Supplier<T>接口被称为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据。
 

Consumer接口:消费数据

java.util.function.Consumer<T>接口中包含抽象方法 void accept(T t) ,意为消费一个指定泛型的数据。

泛型执行什么类型,就可以使用accept方法消费什么类型的数据

andThen方法:作用:需要两个Consumer接口,可以把两个ConSumer接口组合到一起,在对数据进行消费

 

java.util.function.Predicate<T> 接口

Predicate接口中包含一个抽象方法:boolean test(T t):用业指定数据类型数据进行判断的方法

                                                               结果 :符合条件,返回true

                                                                           不符合条件,返回false

默认方法:and,表示 并且关系,也可以用于连接两个判断条件。

方法内部的两个判断条件,也是使用&&运算符连接起来的。
默认方法:or表示或者关系,也可以用于连接两个判断条件

默认方法:negate也表示取反的意思。

 

java.util.function.Function<T,R> 接口用来根据一个类型的数据得到另一个类型的数据

最主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果
Function 接口中有一个默认的 andThen 方法,用来进行组合操作。

 

Stream流:

使用Stream流方式,遍历集合,对集合中的数据进行过滤,关注的是做什么,而不是怎么做。
使用格式:

              list.stream().filter

使用的三个基本步骤:

获取一个数据源(source)可以是集合跟数组 →  数据转换(集合跟数组转换成流)→执行操作获取想要的结果,每次转换原有Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),允许对其操作可以像链条一样排列,变成一个管道。

获取Stream流两种方式:

java.util.stream.Stream<T> 是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)
常用的获取方法:

所有的 Collection 集合都可以通过 stream 默认方法获取流;

default Stream<E> stream()


Stream 接口的静态方法 of 可以获取数组对应的流

static <T> Stream<T> of (T....values)

常用方法:

分为两种:

延迟方法:返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为延迟方法。)
终结方法:返回值类型不再是 Stream 接口自身类型的方法,因此不再支持类似 StringBuilder 那样的链式调用。本小节中,终结方法包括 count 和 forEach 方法。

逐一处理:forEach:

void forEach(Consumer<? super T> action);//该方法接收一个 Consumer 接口函数,会将每一个流元素交给该函数进行处理。
用来遍历流中的数据,遍历之后就不能继续调用Stream流中的其他方法

过滤:filter:

filter 方法将一个流转换成另一个子集流
Stream<T> filter(Predicate<? super T> predicate);

Stream特点:属于管道流,只能被消费(使用)一次。
映射:map

将流中的元素映射到另一个流中,可以使用 map 方法.

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

该接口需要一个 Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。

统计个数:count

用于统计Stream流中元素的个数,是一个终结方法,返回值是一个long类型的整数,不能再调用Stream流中的其他方法
 

取用前几个:limit

Stream<T> limit(long maxSize);//参数是一个long类型,如果集合当前长度大于参数则进行截取;否则不进行操作。

limit方法是一个延迟方法,只是对流中的元素进行截取,返回的是一个新的流,所以可以继续调用Stream流中的其他方法。

跳过前几个:skip

Stream<T> skip(long n);//如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流
组合:concat,静态方法,可通过接口名直接调用

static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)//把a,b两个流合并成一个流

 

方法的引用:

使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿什么参数做什么操作。如何实现简化呢????

@FunctionalInterface
public interface Printable {
     void print(String str);
}

public class Demo01PrintSimple {
 private static void printString(Printable data) 
{
   data.print("Hello, World!");
} 

 public static void main(String[] args) 
{
    printString(s ‐> System.out.println(s));//换成printString(System.out::println);就是方法引用
 }
}

方法引用符::

如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。
引用方法:

通过对象名引用成员方法:前提是对象,成员方法都已经存在

public class MethodRefObject {
  public void printUpperCase(String str) {
    System.out.println(str.toUpperCase());
 }
}

@FunctionalInterface
public interface Printable {
  void print(String str);
}

public class Demo04MethodRef {
  private static void printString(Printable lambda) {
    lambda.print("Hello");
} 
  public static void main(String[] args) {
    MethodRefObject obj = new MethodRefObject();
    printString(obj::printUpperCase);
 }
}

通过类名称引用静态方法:使用前提:类已经存在,静态方法也已存在
java.lang.Math 类中已经存在了静态方法 abs
首先是函数式接口

@FunctionalInterface
public interface Calcable {
  int calc(int num);
}

使用Lambda表达式

public class Demo05Lambda {
  private static void method(int num, Calcable lambda) {
    System.out.println(lambda.calc(num));
}
  public static void main(String[] args) {
    method(‐10, n ‐> Math.abs(n));//method(‐10, Math::abs);简化Lambda
 }
}

通过super引用成员方法:引用父类的成员方法

前提:super是已经存在的,父类的成员方法也是已经存在的

使用this来引用本类的成员方法:

引用的方法就是当前类中的成员方法,那么可以使用“this::成员方法”的格式

类的构造器引用:

构造器的名称与类名完全一样,并不固定。所以构造器引用使用 类名称::new 的格式表示。

数组的构造器引用:也就是使用引用来创建数组

前提是已知创建的是什么类型的数组,数组的长度也是已知的,就可以使用方法引用来创建数组。


java web基础准备:

Junit单元测试:白盒测试中的一种,即需要写代码的,关注程序具体的执行流程

Junit如何使用:

1、定义一个测试类(测试用例),建议,1、类名:被测试的类名Test  2、包名:xxx.xxx.xx.test

2、定义测试方法,可以独立运行,建议:1、方法名:tes测试方法名 2、返回值 void  3、参数列表  空表

3、给方法加@Test

4、添加Junit依赖环境,导入Test包 org.junit.Test
判断结果,一般使用Assert.assertEquals(期望的结果,运算的结果);

 Junit两个注解:

@Before:  一般用于资源申请,所有的测试方法在执行之前都会先执行该方法

@After:释放资源,在所有的测试方法执行完后,都会自动执行该方法


反射:框架设计的灵魂

框架:半成品软件。简化编码。

什么是反射:可以理解就是一个代码框,这个框可以放不同的对象,调用方法时只需要调用这个框就可以,更神奇的是可通过xml预调用。具体使用的例子见扩展:

好处:

1、在程序运行过程中可以操作这些对象

2、可以解耦,增加程序的可扩展性

获取反射的class(字节码)对象方式:

1、class.forName("全类名,也就是全路径名“):将字节码文件加载进内存,返回class对象,多用于配置文件,将类名配置在文件中,读取文件加载类。

如 Class mm=Class.forName("com.lean.ssm.chapter1.Cat");

2、类名.class:通过类名的属性class获取,多用于参数的传递,适合在编译前就知道操作的 Class

如:Class ss = String.class;

3、对象.getClass():方法,在object类中定义的,多用于对象的获取字节码的方式。

String str = new String("Hello");

Class cs = str.getClass();

注:

同一个字节码文件,只会加载一次进内存。不论通过哪种方式获取。

使用class对象的功能:
1、获取成员变量,属性、方法,构造器

Field[] getField()://获取所有public修饰的成员变量,无法获取到私有属性

如:

Class clz = Cat.class;
Field[] fields = clz.getFields();
for (Field field : fields) {
    System.out.println(field.getName());
}

Field[] getField(String name)://获取指定名称public修饰的成员变量

Field[] getDeclaredFields()://获取所有的成员变量,不考虑修饰符

Class clz = Cat.class;
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
    System.out.println(field.getName());
}

Field[] getDeclaredFields(String name)://获取所有指定名称 的成员变量,

注:

Field:成员变量

         1、设置值:

                        void set(Object obj,Object value)

          2、获取值 

                        get(Object obj)

          3、忽略访问权限修饰符的安全检查

                        setAccessible(true):暴力反射

2、获取构造方法

      Constructor<T> getConstructors(class<?>...parameterTypes)

注: 

  Constructor:构造方法

创建对象的

          T newInstance(Object... initargs)

         如果使用空参数构造方法创建对象,操作可以简化:Class对象的NewInstance方法

创建类对象的两种方法:

通过 Class 对象的 newInstance() 方法

Class clz = Cat.class;

Apple apple = (Cat)clz.newInstance();

通过 Constructor 对象的 newInstance() 方法

Class clz = Cat.class;
Constructor constructor = clz.getConstructor();
Cat black = (Cat)constructor.newInstance();

通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。下面的代码就调用了一个有参数的构造方法进行了类对象的初始化。

Class clz = Cat.class;
Constructor constructor = clz.getConstructor(String.class, String.class);
Cat apple = (Cat)constructor.newInstance("红色", “red”);

 

3、获取成员方法

Methrod[] getMethods();//获取所有public修饰的方法

Methrod[] getMethods(String name,class<?>... parameterTypes);//获取指定名称的方法

Method:方法对象

执行方法:

                Object invoke(Object obj,Object...args)

获取方法名称:

               Object getName()

4、获取类名
              类名.getName().也是getName()方法。

注解:

概念:说明程序的。是给编译器看的。

JDK预定义注解

1.@Override:检测被该注解标注的方法是否继承自父类(接口)的。

2.@Deprecated:将该注解标注的内容,已过时

3.@SuppressWarnings:压制警告,需要传参,一般传递 all

自定义注解:

格式:

         元注解

         public @interface 注解名称()

本质:

        就是一个接口 ,继承自 java.lang.annotation 

注解属性:接口里可以定义的抽象方法

       要求:1、属性的返回值类型只有下列取值,基本数据类型、字符串、枚举,以上类型的数组

                   2、定义了属性,在使用时需要给属性赋值,如果定义属性使用default默认初始化时,可以不赋值,若只有一个属性需要赋值,并且属性名称是value,则赋值时value可以省力,直接赋什么值就可以了,数组赋值时,值使用{}包裹。

 

元注解:用于描述注解的注解

@Target:描述注解能够作用的位置

@Retention:描述注解被保留的阶段

@Documented:描述注解是否被抽取到api文档中

@Inherited:描述注解是否被子类继承

在程序中使用(解析)注解:获取注解中定义的属性值

1、获取注解定义的位置的对象(class,method,field)

2、获取指定的注解  使用的方法是  getAnnotation(Class).

3、调用注解中的抽象方法获取配置的属性值

扩展:反射的使用例子

/**
 * Copyright (C), 2015-2021, XXX有限公司
 * FileName: Cat
 * Author:   guang
 * Date:     2021/2/2 17:55
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.lean.ssm.chapter1;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * 〈一句话功能简述〉<br> 
 * 〈〉反射的例子
 *
 * @author guang
 * @create 2021/2/2
 * @since 1.0.0
 */
public class Cat {
    private String color;

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public static void main (String[] args) throws Exception{
        Cat black=new Cat();
        black.setColor("黑色的猫");
        System.err.println("什么颜色的猫? "+ black.getColor());

        //反射实现
        Class mm=Class.forName("com.lean.ssm.chapter1.Cat");
        Method setColorMethrod=mm.getMethod("setColor", String.class);
        Constructor catConstruct=mm.getConstructor();
        Object catob=catConstruct.newInstance();
        setColorMethrod.invoke(catob,"红色的猫");
        Method getColorMethrod=mm.getMethod("getColor");
        System.err.println("什么颜色的猫? " + getColorMethrod.invoke(catob));
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guangod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值