IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> Java8新特性 -> 正文阅读

[PHP知识库]Java8新特性

一、 Lambda表达式

  • 举例:(o1, o2) -> Integer.compare(o1,o2);
  • 格式:
    ->:Lambda操作符 或 箭头操作符
    ->左边:Lambda形参列表,就是接口中的抽象方法的形参列表
    ->右边:Lambda体,即重写的抽象方法的方法体
  • Lambda表达式的本质:作为函数式接口的实例:所有函数式接口的匿名实现类都可以用Lambda表示

1.1 函数式接口

如果一个接口种只声明了一个抽象方法,则此方法称为函数式接口

1.1.1 Java内置四大核心函数式接口

函数式接口参数类型返回类型用途
消费型接口:ConsumerTvoid对类型为T的对象应用操作,包含方法:void accept(T t)
供给型接口:Supplier T返回类型为T的对象,包含方法:T get()
函数型接口:Function<T,R>TR对类型为T的对象应用操作,并返回结果。结果时R类型的对象。包含方法:R apply(T t)
断定型接口 PredicateTboolean确定类型为T的对象是否满足某约束,并返回boolean值。包含方法:boolean test(T t)

1.1.2 Lambda表达式使用举例

例一:

        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("我爱北京天安门");
            }
        };

上述代码等价于:

        Runnable r2 = () -> System.out.println("我爱北京天安门");

例二:

        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        };

Lambda表达式写法;

        Comparator<Integer> com2 = (o1, o2) -> Integer.compare(o1,o2);

方法引用:

        Comparator<Integer> com3 = Integer::compare;

1.2 Lambda表达式使用的六种情况

1.2.1 无参、无返回值

        //第一种情况:无参,无返回值
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("我爱北京天安门");
            }
        };

        Runnable r2 = () -> System.out.println("我爱北京天安门");

1.2.2 有一个参数,但无返回值

        //第二种情况:有一个参数,但无返回值

        Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        con.accept("normal print");

        //Lambda写法
        Consumer<String> con1 = (String s1) -> {
            System.out.println(s1);
        };
        con1.accept("lambda print");

1.2.3 数据类型可以省略,因为可以由编译器推断得出,称为“类型推断”

1.2.2中的Lambda表达式还可以写成:

        Consumer<String> con2 = (s1) -> {
            System.out.println(s1);
        };
        con1.accept("lambda print");

1.2.4 Lambda 若只需要一个参数时,参数的小括号可以省略

即 1.2.3中的表达式可以继续写为

        Consumer<String> con2 = s1 -> {
            System.out.println(s1);
        };
        con1.accept("lambda print");

1.2.5 Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值

        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);
            }
        };

        Comparator<Integer> com2 = (o1, o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };

1.2.6 Lambda体只有一条语句时,return与大括号若有,都可以省略

        Comparator<Integer> com3 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1.compareTo(o2);
            }
        };

        Comparator<Integer> com4 = (o1, o2) -> o1.compareTo(o2);

1.3 方法引用和构造器引用

1.3.1 方法引用

  • 当要传递给Lambda体的操作(重写的方法),已经有实现的方法了,就可以使用方法引用
  • 方法引用是Lambda表达式深层次的表达。方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方向,可以认为是Lambda表达式的一个语法糖。
  • 要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值保持一致(针对情况一和情况二)
  • 格式:使用操作符::将类(或对象)与方法名分隔开
  • 三种主要使用情况

情况一:对象::非静态方法名
情况二:类::静态方法名
情况三:(难点)类::非静态方法名

1.3.1.1 方法引用示例

① 对象 :: 实例方法
    /*
    Consumer中的void accept(T t)
    PrintStream中的void println(T t)
     */
    @Test
    public void test1(){

        //Lambda表达式
        Consumer<String> con1 = str -> System.out.println(str);
        con1.accept("beijing");

        //方法调用一: 对象 :: 实例方法
        PrintStream ps = System.out;
        Consumer<String> con2 = ps :: println;
        con2.accept("北京");

    }
    
    
    /*
    Supplier中的 T get()
    Employee中的String getName()
     */
    @Test
    public void test2(){
        
        //Lambda表达式
        Employee emp = new Employee(1001,"Tom",12);
        Supplier<String> sup1 = () -> emp.getName();
        System.out.println(sup1.get());
        
        //方法引用
        Supplier<String> sup2 = emp :: getName;
        

    }
②类 :: 静态方法
    //情况二:类 :: 静态方法
    /*
    Comparator 中的int compare(T t1,T t2)
    Integer 中的 int compare(T t1,T t2)
     */
    @Test
    public void test3() {

        //Lambda表达式
        Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1, t2);
        System.out.println(com1.compare(12, 21));

        //方法引用
        Comparator<Integer> com2 = Integer::compare;
    }

    /*
    Function中的R apply(T t)
    Math 中的 Long round(Double d)
     */
    @Test
    public void test4() {

        //lambda表达式
        Function<Double, Long> func1 = d -> Math.round(d);
        func1.apply(2.3);

        //方法引用
        Function<Double, Long> func2 = Math::round;
        func1.apply(5.4);
    }
③ 类 :: 实例方法 (难点)
    //情况三:类 :: 实例方法(难点)
    /*
    Comparator 中的int compare(T t1,T t2)
    String 中的 int t1.compareTo(t2)
     */
    @Test
    public void test5(){

        //Lambda
        Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);

        //方法引用
        Comparator<String> com2 = String :: compareTo;

    }

    /*
    BiPredicate 中的boolean test(T T1,T t2)
    String 中的 boolean t1.equals(t2)
     */
    @Test
    public void test6(){

        //Lambda
        BiPredicate<String,String> pre1 = (s1,s2) -> s1.equals(s2);

        //方法引用
        BiPredicate<String,String> pre2 = String :: equals;

    }

    /*
    Function 中的 R apply(T t)
    Employee 中的 String getName();
     */
    @Test
    public void  test7(){


        Function<Employee,String> func = new Function<Employee, String>() {
            @Override
            public String apply(Employee employee) {
                return null;
            }
        };

        //Lambda
        Employee employee = new Employee(1003, "Alice", 24);
        Function<Employee,String> func1 = e -> e.getName();
        func1.apply(employee);

        //方法引用
        Function<Employee,String> func2 = Employee :: getName;

    }

1.3.2 构造器引用

和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一样
抽象方法的返回值类型即为构造器所属的类

    //构造器引用
    //Supplier 中的 T get()
    @Test
    public void test1(){
        //原始写法
        Supplier<Employee> supplier = new Supplier<Employee>() {
            @Override
            public Employee get() {
                return null;
            }
        } ;

        //Lambda
        Supplier<Employee> sup1 = () -> new Employee();

        //构造器引用
        Supplier<Employee> sup2 = Employee::new;
    }

    //Function 中的 R apply(T t)
    @Test
    public void test2(){
        Function<Integer,Employee> func1 = id -> new Employee(id);
        Employee employee = func1.apply(1001);

        //构造器引用
        Function<Integer,Employee> func2 = Employee :: new;
        Employee employee1 = func2.apply(1002);

    }

    //BiFunction中的 R apply(T t,U u)
    @Test
    public void test3(){

        BiFunction<Integer,String,Employee> func1 = (id,name) -> new Employee(id,name);
        func1.apply(1001,"Tom");

        //构造器引用
        BiFunction<Integer,String,Employee> func2 = Employee :: new;
    }

1.3.3 数组引用

可以把数组看作是一个特殊的类,数组引用的方法就和构造引用一样了

    //数组引用
    //Function中的apply(T t)
    @Test
    public void test4(){

        Function<Integer,String[]> func1 = length -> new String[length];
        String[] arr1 = func1.apply(5);
        Arrays.toString(arr1);

        //数组引用
        Function<Integer,String[]> func2 = String[] :: new;
        String[] arr2 = func2.apply(10);
        Arrays.toString(arr2);

    }

二、StreamAPI

Stream API 可以对集合数据进行类似于SAL执行的数据库查询。也可以使用Stream API 来并行执行操作,建简而言之,Stream API提供了一种高效且易于使用的处理数据的方式

2.1 为什么要使用Stream API

  • 实际开发中,项目中多数数据源都来自Mysql,Oracle关系型数据库等。但现在数据源可以更多了,有MongDB,Radis等,而这些NoSQL(非关系型数据库)的数据就需要Java层面去处理。
  • Stream 和Collection集合的区别:Collection是一种静态的内存数据结构,而Stream是有关计算的。前者主要面向内存,存储在内存中,后者主要是面向CPU,通过CPU实现计算

Stream是什么

  • Stream是数据渠道,用于操作数据源就(集合、数组等)所生产的元素序列
    集合讲的是数据,Stream讲的是计算

注意项

① Stream 自己不会存储元素
② Stream 不会改变源对象。相反,他们会返回一个持有结果的新Steam
③ Stream 操作是延迟执行的。这意味着他们会等到需要结果时才执行。

2.2 Stream的操作的三个步骤

2.2.1、创建 Stream

一个数据源(如:集合、数组),获取一个流

通过集合创建Stream

Java8的Collection接口被扩展,提供了两个获取流的方法

default Stream<E> stream() :返回一个顺序流
default Stream<E> parallelStream() :返回一个并行流

        //方式一、通过集合
        List<Employee> employees = EmployeeDate.getEmployees();

        //1.1 default Stream<E> stream() :返回一个顺序流
        Stream<Employee> stream = employees.stream();

        //1.2 Stream<E> parallelStream() :返回一个并行流
        Stream<Employee> employeeStream = employees.parallelStream();

通过数组创建Stream

Java8 中的Arrays的静态方法 stream()可以获取数组流
static <T> Stream<T> stream(T[] array):返回一个流

        //方式二、通过数组

        //调用Arrays类的static <T> Stream<T> stream(T[] array):返回一个流
        int [] arr = new int[]{1,2,3,4,5,6};
        IntStream stream1 = Arrays.stream(arr);

        Employee e1 = new Employee(1001,"Tom");
        Employee e2 = new Employee(1002,"Bob");
        Employee e3 = new Employee(1003,"Siri");
        Employee e4 = new Employee(1004,"Alix");
        Employee[] ees = new Employee[]{e1,e2,e3,e4};

        Stream<Employee> stream2 = Arrays.stream(ees);

通过Stream的of()

调用Stream类静态方法of(),通过显示值创建一个流。它可以接收任意数量的参数。

        //方式三
        Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6);

创建无限流

        //迭代
        //遍历前十个偶数
        Stream.iterate(0,t->t+2).limit(10).forEach(System.out::println);


        //生成
        Stream.generate(Math::random).limit(10).forEach(System.out::println);

2.2.2、中间操作

一个中间操作链,对数据源的数据进行处理,只有在需要结果的时候才会去执行

筛选与切片

    //筛选与切片
    @Test
    public void test1(){
        List<Employee> employees = EmployeeDate.getEmployees();

        Stream<Employee> stream = employees.stream();

        //filter(Predicate p)——接收Lambda,从流中排除某些元素
        //查询员工表中年龄小于23岁地员工信息
        stream.filter(e -> e.getAge() < 23).forEach(System.out::println);
        System.out.println();

        //limit(n)——截断流,使其元素不超过给定数量,相当于获取前n个元素
        employees.stream().limit(3).forEach(System.out::println);
        System.out.println();

        //skip(n) ——跳过元素,返回一个扔掉了前n个元素的流,相当于获取第n个元素以后的元素。若元素不足n个,则返回
        employees.stream().skip(3).forEach(System.out::println);
        System.out.println();

        //distinct()——筛选 ,通过流所生成的元素的hashCode() 和 equals() 去除重复元素
        System.out.println(employees);
        employees.stream().distinct().forEach(System.out::println);
    }

输出:

Employee{id=1002, name='刘兰', age=19}
Employee{id=1007, name='郑兰', age=22}
Employee{id=1007, name='郑兰', age=22}

Employee{id=1001, name='周兰', age=23}
Employee{id=1002, name='刘兰', age=19}
Employee{id=1003, name='张兰', age=28}

Employee{id=1004, name='李兰', age=23}
Employee{id=1005, name='王兰', age=26}
Employee{id=1006, name='杨兰', age=24}
Employee{id=1007, name='郑兰', age=22}
Employee{id=1005, name='王兰', age=26}
Employee{id=1006, name='杨兰', age=24}
Employee{id=1007, name='郑兰', age=22}

[Employee{id=1001, name='周兰', age=23}, Employee{id=1002, name='刘兰', age=19}, Employee{id=1003, name='张兰', age=28}, Employee{id=1004, name='李兰', age=23}, Employee{id=1005, name='王兰', age=26}, Employee{id=1006, name='杨兰', age=24}, Employee{id=1007, name='郑兰', age=22}, Employee{id=1005, name='王兰', age=26}, Employee{id=1006, name='杨兰', age=24}, Employee{id=1007, name='郑兰', age=22}]
Employee{id=1001, name='周兰', age=23}
Employee{id=1002, name='刘兰', age=19}
Employee{id=1003, name='张兰', age=28}
Employee{id=1004, name='李兰', age=23}
Employee{id=1005, name='王兰', age=26}
Employee{id=1006, name='杨兰', age=24}
Employee{id=1007, name='郑兰', age=22}

映射

    @Test
    public void test2(){
        //map(Function f) ——接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每一个元素上,并映射其成为一个新的元素
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        list.stream().map(String::toUpperCase).forEach(System.out::println);

        //练习1:获取员工姓名长度大于3的员工的姓名
        List<Employee> employees = EmployeeDate.getEmployees();
        Stream<String> namesStream = employees.stream().map(Employee::getName);
        namesStream.filter(name -> name.length() > 3).forEach(System.out::println);

        //练习二、
        Stream<Stream<Character>> streamStream = list.stream().map(StreamAPITest1::stringToStream);
        streamStream.forEach(s->{
            s.forEach(System.out::println);
        });

        System.out.println();

        //flapMap(Function f) ——接收一个函数作为参数,将流中的每一个值都换成另外一个流,然后把所以流练成一个流
        Stream<Character> characterStream = list.stream().flatMap(StreamAPITest1::stringToStream);
        characterStream.forEach(System.out::println);
    }

stringToStream(String s)方法:

    //将字符串中的多个字符构成的集合转换为对应的Stream的实例
    public static Stream<Character> stringToStream(String s){
        ArrayList<Character> list = new ArrayList<>();
        for(Character c : s.toCharArray()){

            list.add(c);
        }
        return list.stream();
    }

排序

    //排序
    @Test
    public void test(){
        //sorted()——自然排序
        List<Integer> li = Arrays.asList(12, 65, 78, 1, 23, 3, 0, 8, -12);
        li.stream().sorted().forEach(System.out::println);

        //异常:Employee 没有实现Comparable接口
//        List<Employee> employees = EmployeeDate.getEmployees();
//        employees.stream().sorted().forEach(System.out::println);

        //sorted(Comparator com) —— 定制排序
        List<Employee> employees = EmployeeDate.getEmployees();
        employees.stream().sorted((e1,e2) -> {

            int ageValue =  Integer.compare(e1.getAge(),e2.getAge());
            if (ageValue != 0){
                return ageValue;
            }else {
                return  e1.getName().compareTo(e2.getName());
            }

        }).forEach(System.out::println);

    }

2.2.3、终止操作(终端操作)

一旦执行终止操作,就执行中间操作链,并产生结果。之后不可以再被使用

匹配与查找

    //匹配与查找
    @Test
    public void test1(){

        List<Employee> employees = EmployeeDate.getEmployees();

        //boolean allMatch(Predicate p)  检查是否匹配所有元素
        //boolean anyMatch(Predicate p)  检查是否至少匹配一个元素
        //boolean noneMatch(Predicate p)  检查是否没有匹配的元素

        //例:是否所有的员工年龄都大于18
        boolean b = employees.stream().allMatch(e -> e.getAge() > 18);
        System.out.println(b);


        //findFirst 返回第一个元素
        //FindAny   返回当前流中的任意元素
        Optional<Employee> first = employees.stream().findFirst();
        Optional<Employee> any = employees.stream().findAny();

        System.out.println(first);
        System.out.println(any);
        //count 返回流中元素的总个数
        long count = employees.stream().count();
        System.out.println(count);


        //max(Comparator c) 返回流中最大值
        Stream<Integer> ages = employees.stream().map(e -> e.getAge());
        Optional<Integer> max = ages.max(Double::compare);
        System.out.println(max);

        //min(Comparator c) 返回流中最小值
        //返回年龄最小的员工
        Optional<Employee> min = employees.stream().min((e1, e2) -> Double.compare(e1.getAge(), e2.getAge()));
        System.out.println(min);

        //froEach(Consumer c) 内部迭代
        employees.stream().forEach(System.out::println);
    }

归约

    //归约
    @Test
    public void test2() {

        //reduce(T identify,BinaryOperator) 可以将流中元素反复结合起来,得到一个值。返回T
        //例:计算1 - 10的自然数的和
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer sum = list.stream().reduce(0, Integer::sum);//identity;初始值
        System.out.println(sum);


        //reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回Optional<T>
        //例、计算公司所有员工的年龄和
        List<Employee> employees = EmployeeDate.getEmployees();
        Stream<Integer> agesStream = employees.stream().map(Employee::getAge);
        Optional<Integer> sumAge = agesStream.reduce(Integer::sum);
//        Optional<Integer> sumAge = agesStream.reduce((a1, a2) -> a1 + a2);
        System.out.println(sumAge);


    }

收集

collect (Collector c) 将流转换为其他形式,接收一个Collector接口的实现,用于给Steam中元素做汇总的方法
Collector接口中方法的实现决定了,如何对流执行收集的操作(如收集到List、Set、Map)

    //收集
    @Test
    public void test3(){

        //collect (Collector c) 将流转换为其他形式,接收一个Collector接口的实现,用于给Steam中元素做汇总的方法
        //Collector接口中方法的实现决定了,如何对流执行收集的操作(如收集到List、Set、Map)
        //查找工资年龄大于20的员工,结果返回为一个List或Set
        List<Employee> employees = EmployeeDate.getEmployees();

        //收集到List
        List<Employee> employeeList = employees.stream().filter(e -> e.getAge() > 20).collect(Collectors.toList());
        employeeList.forEach(System.out::println);

        //收集到Set
        Set<Employee> employeeSet = employees.stream().filter(e -> e.getAge() > 20).collect(Collectors.toSet());
        employeeSet.forEach(System.out::println);


    }

三、Optional类

  • 来源:为了解决空指针异常,Google公司著名的Guava项目映入Optional类,Guava通过使用检查空值的方式来防止代码污染。收到Google Guava的启发,Optional类已经成为Java8类库的一部分
  • Opyional类(java.util.Optional)是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用null,表示一个值不存在,现在Optional可以更好的表达这个概念。并且可以更好的避免空指针异常.
  • Potional类的Javadoc描述如下:这是一个可以为unll的容器对象,如果值存在则isPresent()方法返回true,调用get()方法会返回该对象。

3.1 Optional类中的方法

Optional类提供了很多方法,使得我们不用显式地进行空值检测

3.1.1 创建Optional类对象的方法

Optional.of(T t) 创建一个Optional实例,t必须非空

        Girl girl= new Girl();
        Optional<Girl> girl1 = Optional.of(girl);

        System.out.println("************");
        girl = null;//java.lang.NullPointerException
        Optional<Girl> girl2 = Optional.of(girl);

输出:

************

java.lang.NullPointerException
	at java.util.Objects.requireNonNull(Objects.java:203)
	at java.util.Optional.<init>(Optional.java:96)
	at java.util.Optional.of(Optional.java:108)

由结果可知,第一次实例化对象成功,第二次空指针异常

Optional.empty():创建一个空的Optional实例

在这里插入图片描述

Optional.ofNullable(T t): t可以为null

   @Test
   public void test3(){
       Girl girl= new Girl();
       Optional<Girl> girl1 = Optional.ofNullable(girl);
       System.out.println(girl1);
       
       Optional<Girl> girl2 = Optional.ofNullable(null);
       System.out.println(girl2);
   }

输出

Optional[Girl{name='null', age=0}]
Optional.empty

3.1.2 获取Optional容器对象

T orElse(T other):

如果有值则将其返回,否则返回指定的other对象

        Girl girl = new Girl();
        Optional<Girl> girl1 = Optional.ofNullable(girl);
        Optional<Girl> girl2 = Optional.ofNullable(null);

        //orElse(T t)如果当前的Option内部封装的t是非空的,则返回内部t
        //如果内部的t是空的,则返回orElse()方法中的参数
        Girl girl3 = girl1.orElse(new Girl("刘亦菲", 30));
        Girl girl4 = girl2.orElse(new Girl("刘亦菲", 30));
        System.out.println(girl3);
        System.out.println(girl4);

输出

Girl{name='null', age=0}
Girl{name='刘亦菲', age=30}

ofNullable + orElse的一个综合使用

getGirlName类:

    public String getGirlName(Boy boy) {
        Optional<Boy> boyOptional = Optional.ofNullable(boy);
        //此时boy1一定非空
        Boy boy1 = boyOptional.orElse(new Boy(new Girl("杨幂", 31)));

        Girl girl = boy1.getGirl();

        Optional<Girl> girlOptional = Optional.ofNullable(girl);
        //girl1一定非空
        Girl girl1 = girlOptional.orElse(new Girl("迪丽热巴", 30));

        return girl1.getName();
    }

测试:

    @Test
    public void test4(){

        Boy boy = null;
        String girlName = getGirlName(boy);
        System.out.println(girlName);

        Boy boy1 = new Boy();
        String girlName1 = getGirlName(boy1);
        System.out.println(girlName1);

        Boy boy2 = new Boy(new Girl());
        String girlName2 = getGirlName(boy2);
        System.out.println(girlName2);

        Boy boy3 = new Boy(new Girl("初恋女友",18));
        String girlName3 = getGirlName(boy3);
        System.out.println(girlName3);

    }

输出:

杨幂
迪丽热巴
null
初恋女友
  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-09-18 09:51:10  更:2021-09-18 09:52:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:50:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码