反射、枚举以及lambda表达式

news2024/9/22 7:24:32

1. 反射

1.1 定义

java的.class文件在运行时会被编译为一个Class对象,既然是对象,那么我们就可以通过一定的方式取到这个对象,然后对于这个对象进行一系列操作(改变原本类的属性、方法)。

这个操作就是反射,反射会像一面照妖镜一样,将所有的类“照”出来,不管它是否是private的还是protected,都可以进行访问、创建、修改。

反射的一系列操作都是动态的。

1.2 用途(了解)

  1. 在日常的第三方应用开发中,经常有某个属性或者方法只对于系统进行开放,这时可以利用反射进行获取。
  2. 开发各种通用框架也可以用到。

1.3 反射出的基本信息

java程序中许多对象在运行时会出现两种类型:运行时类型(RTTI)和编译时类型,例如Person p = new Student();这句代码中p在编译时类型为Person,运行时类型为Student。程序需要在运行时发现对象和类的真实 信息。而通过使用反射程序就能判断出该对象和类属于哪些类。

1.4 反射相关的类(重要)

说明
Class类代表类的实体,在运行的java程序中表示类和接口
Field类代表类的成员变量
Constructor类代表类的构造方法
Method类代表类的方法

1.5 获得Class对象的三种方式

package ReflectDemo;

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

public class ReflectDemo {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ClassNotFoundException {
        // 方式1
        Class<?> student1 = Student.class;
        // 方式2
        Class<?> student2 = Class.forName("ReflectDemo.Student");
        // 方式3
        Student studentTmp = new Student("",1);
        Class<?> student3 = studentTmp.getClass();

        // 验证是不是同一个Class对象
        System.out.println(student1 == student2);
        System.out.println(student1 == student3);
    }
}

三种方式:

  1. 使用 “对象名.class” 进行获得
  2. 使用 "Class.forName(“类的路径”)"进行获得
  3. 使用 “已经构造出来的对象.getClass()” 进行获得

只有一个Class对象的原因:
在这里插入图片描述

所以通过反射只能得到同一个Class对象。

1.6 反射的使用——Class类中的相关方法(重要)

出现Declared就能够获取私有变量/方法。

1.6.1 常用获得类相关的方法

方法说明
getClassLoader()获得类的加载器
getDeclaredClass()返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有的
forName(String className)根据类名返回类的对象
getName()获得类的完整路径名字

创建的Person测试类(包含public、private内部类,接口,各种属性):

package ReflectDemo;

public class Person implements Comparable<Person>{
    public String name;
    private int id;
    private int age;

    @Override
    public int compareTo(Person o) {
        return o.age - this.age;
    }

    interface interfaceTest{};
    public class PublicInnerClass {}
    private class PrivateInnerClass {}

    public Person(String name, int id) {
        this.name = name;
        this.id = id;
    }

}

测试代码:

package ReflectDemo;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;

public class ReflectTest {
    public static void main(String[] args) {
        Class<?> cls;
        try {
            cls = Class.forName("ReflectDemo.Person");
            /*// 获取Person类内部的public类、接口,返回一个数组
            Class<?>[] classes = cls.getClasses();*/

            // 获取Person类内部的包括private的类、接口,返回一个数组
            Class<?>[] classes = cls.getDeclaredClasses();
            System.out.println(Arrays.toString(classes));

            System.out.println(Person.class.getName());
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

运行结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.6.2 (重要)常用获得类属性的方法(以下与Field相关)

方法说明
getField(String name)获得某个公有属性(参数为属性名称)
getFields()获得所有公共属性(返回值为Fields数组)
getDeclaredField(String name)获得某个属性(参数为属性名称、不分权限)
getDeclaredFields()获得某个属性(返回值为Fields数组、不分权限)

示例代码:

package ReflectDemo;

import java.lang.reflect.Field;
import java.util.Arrays;

public class ReflectDemo3 {
    public static void main(String[] args) throws NoSuchFieldException {
        Class<?> personClass = Person.class;

        // 获得公有属性
        Field name = personClass.getField("name");
        Field[] fields = personClass.getFields();

        System.out.println("获得某个公有属性");
        System.out.println(name);
        System.out.println("获得所有公有属性");
        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println("获得某个属性(不分权限)");
        //获得某个属性(不分权限)
        System.out.println(personClass.getDeclaredField("id"));

        System.out.println("获得所有属性(不分权限)");
        // 获得所有属性(不分权限)
        System.out.println(Arrays.toString(personClass.getDeclaredFields()));
    }
}

运行结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.6.3 (了解)获得类中注解相关的方法

方法说明
getAnnotation(Class annotationClass)返回该类中与参数类型匹配的公有注解对象
getAnnotations()返回该类所有的公有注解对象
getDeclaredAnnotation(Class annotationClass)返回该类中与参数类型匹配的所有注解对象
getDeclaredAnnotations()返回该类所有的注解对象

1.6.4 (重要)获得类中构造器相关的方法(以下方法返回值为Constructor相关)

方法说明
getConstructor(Class… parameterTypes)获得该类中与参数类型匹配的公有构造方法
getConstructors()得该类的所有公有构造方法
getDeclaredConstructor(Class… parameterTypes)获得该类中与参数类型匹配的构造方法
getDeclaredConstructors()获得该类所有构造方法

代码:

package ReflectDemo;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;

public class ReflectDemo4 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> personClass = Person.class;

        System.out.println("获得类中特定参数的公有构造方法");
        Constructor<?> personConstructor = personClass.getConstructor(String.class, int.class);
        System.out.println(personConstructor);

        System.out.println("使用特定参数的公有构造方法");
        System.out.println(personConstructor.newInstance("王五", 2023).toString());

        System.out.println("获得类中所有的公有构造方法");
        Constructor<?>[] personConstructors = personClass.getConstructors();
        System.out.println(Arrays.toString(personConstructors));


        System.out.println("获得类中所有的公有构造方法");
        Constructor<?>[] personConstructors2 = personClass.getDeclaredConstructors();
        System.out.println(Arrays.toString(personConstructors2));

        System.out.println("获得类中特定参数的、不分权限的构造方法");
        Constructor<?> personConstructor2 = personClass.getDeclaredConstructor(String.class);
        personConstructor2.setAccessible(true);// 必须设置为true,确认对这个私有方法进行操作
        System.out.println(personConstructor2);

        System.out.println(personConstructor2.newInstance("老六").toString());
    }
}

运行结果:
在这里插入图片描述

1.6.5 (重要)获得类中方法相关的方法(以下方法返回值为Method相关)

方法获取到后,需要使用invoke进行调用,第一个参数是这个方法作用的对象,后面的参数是要传到函数中的参数。

方法说明
getMethod(String name, Class… parameterTypes)获得该类某个公有的方法
getMethods()获得该类所有公有的方法
getDeclaredMethod(String name, Class… parameterTypes)获得该类某个方法
getDeclaredMethods()获得该类所有方法
package ReflectDemo;

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

public class ReflectDemo5 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> personClass = Person.class;

        Constructor<?> perspnConstructor = personClass.getConstructor(String.class, int.class);
        Person p = (Person) perspnConstructor.newInstance("老七", 2023001);
        System.out.println(p.toString());

        Method setName = personClass.getMethod("setName", String.class);
        p.setName("老八");
        System.out.println(p.toString());

        Method eat = personClass.getMethod("eat");
        eat.invoke(p);// 无参函数调用

        Method swim = personClass.getDeclaredMethod("swim");
        swim.setAccessible(true);// 确认修改访问权限
        swim.invoke(p);
    }
}

运行结果:
在这里插入图片描述

1.5 反射优点和缺点

优点:

  1. 能够获取本来访问受限的属性、方法。
  2. 增强了程序的灵活性,降低耦合度
  3. 已经运用在了很多流行的框架上,如:Struts、Hibernate、Spring 等等。

缺点:

  1. 使用反射的代码效率较低。
  2. 破坏程序封装性。
  3. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 。

1.6 重要总结

  1. 反射的意义

意义在于获取一些只对于系统开放的、不让外界看到的方法、属性。

  1. 反射的重要类:

Field类,Constructor类,Method类,Class类。

  1. 合理利用反射,不要轻易使用。

2. 枚举

将一组常量组织起来,同c语言的枚举相同,已经定义好的枚举中,常量就代表这个符号,这个符号也代表常量。

场景:错误状态码,消息类型,颜色的划分,状态机等等。

本质:继承自Enum这个类。(如同所有的对象都继承自Object类一样,都是隐式继承)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.1 常用方法

方法说明
values()获得枚举类中所有的成员
ordinal()获得成员在枚举类中的索引位置
name()获得枚举成员的名称
valueOf()将普通字符串转换为枚举实例
compareTo()返回成员在定义时的顺序(将索引位置进行相减)

代码:

package EnumDemo;

public class Demo2 {
    public static void main(String[] args) {
        Color[] color = Color.values();

        for (Color color1 : color) {
            // ordinal的编号改变不了,这是枚举成员在类中的索引位置
            System.out.println(color1.ordinal() +" "+ color1.name());
        }

        // 将编号与name联系起来
        System.out.println(Color.getEnumKey(4));

        Color red = Color.RED;
        Color blue = Color.BLUE;
        System.out.println(red.compareTo(blue));// 索引位置相减
    }
}

运行结果:
在这里插入图片描述

枚举的构造方法默认是私有的!所以还可以在枚举类中加上自己定义的构造函数,直接在成员后面进行初始化。

package EnumDemo;

public enum Color {
 RED(4,"红色"),GREEN(5,"绿色"),BLUE(6,"蓝色");
 private int key;
 private String name;

 Color(int key, String name) {
     this.key = key;
     this.name = name;
 }

 public static Color getEnumKey(int key) {
     // 遍历整个枚举类看有没有key
     for (Color e : Color.values()) {
         if (key == e.key) {
             return e;
         }
     }
     return null;
 }
     // err,默认是私有的
//    public Color(int num, String color) {}
//    RED,GREEN,BLUE;
}

2.2 枚举的优缺点

优点:

  1. 统一组织,便于管理常量,优于final
  2. 简单安全
  3. 枚举类有内置方法,书写更优雅

缺点:

  1. 不可被继承,无法扩展

但是为单例模式提供了很好的思路。

2.3 枚举与反射

枚举既然安全性这么高,那么能不能通过反射获取到枚举类呢?做个实验验证一下。

package EnumDemo;

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

public class Demo3 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> enumClass = Color.class;

        Constructor<?> enumClassConstructor = enumClass.getDeclaredConstructor(int.class, String.class);
        enumClassConstructor.setAccessible(true);
        Color o = (Color) enumClassConstructor.newInstance(1, "黑色");
        System.out.println(o);
    }
}

运行结果:
在这里插入图片描述

报错提示我们并没有这个构造方法,但是我们的构造方法就是两个参数:

Color(int key, String name) {
    this.key = key;
    this.name = name;
}

是不是由于隐藏的super()?还需要参数给父类Enum进行初始化?

Enum类构造方法:

/**
 * Sole constructor.  Programmers cannot invoke this constructor.
 * It is for use by code emitted by the compiler in response to
 * enum type declarations.
 *
 * @param name - The name of this enum constant, which is the identifier
 *               used to declare it.
 * @param ordinal - The ordinal of this enumeration constant (its position
 *         in the enum declaration, where the initial constant is assigned
 *         an ordinal of zero).
 */
protected Enum(String name, int ordinal) {
    this.name = name;
    this.ordinal = ordinal;
}

插播:(在给出源码的时候,源码上的注解已经能够说明不能进行invoke构造了。)

确实,看来父类还需要两个参数进行构造,修改代码如下:

package EnumDemo;

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

public class Demo3 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> enumClass = Color.class;
        // 函数的参数需要有四个,前两个是父类进行使用,后两个才是自己写的本身的参数
        Constructor<?> enumClassConstructor = enumClass.getDeclaredConstructor(String.class, int.class,int.class, String.class);
        enumClassConstructor.setAccessible(true);
        Color o = (Color) enumClassConstructor.newInstance(1, "黑色");
        System.out.println(o);
    }
}

运行结果:
在这里插入图片描述

看来参数传正确也不能够调用,报错指出不能够使用反射进行获取。

然后再返回来看源码中的注释部分:

枚举的源码注释:

** Sole constructor. Programmers can not invoke this constructor.* ** It is for use by code emitted by the compiler in response to* *** enum type declarations.

唯一的构造器,程序员不能够激活这个构造器,它它供编译器在响应 enum类型声明时发出的代码使用。

newInstance()的源码

在这里插入图片描述

结论:

  1. 枚举类不能够使用反射获取实例。
  2. 枚举可以避免反射和序列化。
  3. 枚举简单安全、有内置函数、能够组织常量,便于管理,优于final

2.4 枚举与单例模式

package EnumDemo;

enum SingleEnum {
    INSTANCE;
    public SingleEnum getInstance() {
        return INSTANCE;
    }
}
public class Demo4 {
    public static void main(String[] args) {
        SingleEnum singleEnum1 = SingleEnum.INSTANCE;
        SingleEnum singleEnum2 = SingleEnum.INSTANCE;
        System.out.println(singleEnum2 == singleEnum1);
    }
}

用枚举实现单例模式简单优雅。

3. lambda表达式

3.1 背景

Lambda表达式是java SE 8中一个重要的新特性。它能够简化匿名内部类(函数式接口)的代码量,只关注怎么执行这个代码,而不是无用的创建过程。

3.2 语法

基本原则要遵循:

  1. (parameters)->expresstion
  2. (parameters)->{statements;}

lambda表达式由三部分组成:

  1. parameters:参数部分,类似于普通方法当中的形参部分。

这里的参数可以明确声明,也可以省略,原则是:能推导出来,就能省略。

  1. 比如参数只有一个,那么可以省略类型,同时也可以省略小括号()
  2. 比如参数有多个,但是类型都一样,那么也可省略类型
  1. ->:lambda表达式的标志性语法结构,可以理解为,“被用于”

  2. 方法体:相当于普通方法的方法体,可以是表达式,也可以是代码块,同样,也可以省略。

可推导即可省略:

  1. 如果这个方法只有一个return语句,那么就可以省略return,省略{}

3.2.1 函数式接口

是一个内部仅含一个抽象方法的接口。

注解:@FunctionalInterface

3.3 使用

package LambdaDemo;


public class demo1 {
    // 无返回值无参数
    @FunctionalInterface
    public 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 static void main(String[] args) {
        // 相当于已经覆写了这个接口的test方法
        NoParameterNoReturn a1 = ()-> System.out.println("无参数无返回值");
        a1.test();

        OneParameterNoReturn a2 = ((a)->{
            System.out.println("无返回值一个参数,参数为:" + a);
        });
        a2.test(1);

        MoreParameterNoReturn a3 = ((a,b) -> {
            System.out.println("无返回值多个参数,参数有:" + a + " "+ b);
        });
        a3.test(1,2);

        NoParameterReturn a4 = ()->{
            System.out.print("有返回值无参数,返回值为:");
            return 4;
        };
        System.out.println(a4.test());

        OneParameterReturn a5 = ((a)->{
            System.out.print("有返回值一个参数,参数为:" + a + "返回值为平方:");
            return a*a;
        });
        System.out.println(a5.test(5));

        MoreParameterReturn a6 = ((a,b)-> {
            System.out.print("有返回值多参数, 参数为:" + a +" "+ b+ "返回值为和:");
            return a+b;
        });

        System.out.println(a6.test(6, 7));
    }
}

运行结果:

在这里插入图片描述

3.3.1 精简规则

在这里插入图片描述

3.4 变量捕获

3.4.1 匿名内部类

匿名内部类就是没有名字的类,用过一次就用不了的类。比如创建线程的时候可以创建匿名内部类进行创建线程。举个例子:

package LambdaDemo;

class Test{
    public void func() {
        System.out.println("未被重写的func()方法");
    }
}
public class Demo2 {
    public static void main(String[] args) {
        Test t = new Test(){
            public void func() {
                System.out.println("重写func()");
            }
        };

        t.func();

        Test t2 = new Test();
        t2.func();
    }
}

运行结果:
在这里插入图片描述

这里就是创建了一个匿名的Test类,直接对类中的func()方法进行重写。因为只想要利用一下Test类中的func()方法。

3.4.2 匿名内部类的变量捕获

package LambdaDemo;

import javax.smartcardio.TerminalFactory;

class Test{
    public void func() {
        System.out.println("未被重写的func()方法");
    }
}
public class Demo2 {
    public static void main(String[] args) {
        int a = 100;
        Test t = new Test(){
            public void func() {
                System.out.println("重写func()");
//                a = 99;// err, 不允许改变变量
                System.out.println("捕获到变量,值为:"+ a);
            }
        };
        t.func();

    }
}

结论:

  1. 匿名内部类中的捕获的变量必须是final,或者与final等价(未经修改的变量)。

3.4.4 Lambda的变量捕获

package LambdaDemo;

@FunctionalInterface
interface Test2{
    abstract void func();
}

public class Demo3 {
    public static void main(String[] args) {
        int a = 100;
        Test2 t = (()->{
//            a = 99;// err
            System.out.println("重写func()");
            System.out.println(a);
        });
        t.func();
    }
}

结论与匿名内部类相同,方法体中只能由final或者等价于final 的变量存在。

4. Lambda在集合当中的使用

4.1 Collection接口

forEach**() 方法源码:**

default void forEach(Consumer action) { 
    Objects.requireNonNull(action); 
    for (T t : this) { 
        action.accept(t); 
    } 
}

该方法表示:对容器中的每个元素执行action指定的动作 。

使用示例:

package LambdaDemo;

import java.util.ArrayList;
import java.util.function.Consumer;

public class Demo4 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");

        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                // 使用accept方法对 list 中每个元素执行相同的操作
                System.out.print(s + " ");
            }
        });

        System.out.println("\r\n使用lambda表达式改写后:");
        list.forEach((s)-> System.out.print(s + " "));
    }
}

运行结果:

在这里插入图片描述

4.2 List接口

sort()方法的源码

default void sort(Comparator<? super E> c) {
    Object[] a = this.toArray();
    Arrays.sort(a, (Comparator) c);
    ListIterator<E> i = this.listIterator();
    for (Object e : a) {
        i.next();
        i.set((E) e);
    }
}

该方法表示:对容器中的元素进行指定规则的排序。

使用示例:

package LambdaDemo;

import ReflectDemo.Person;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Consumer;

public class Demo5 {
    public static void main(String[] args) {
        Person p1 = new Person("张三",2023);
        Person p2 = new Person("李四",2022);
        Person p3 = new Person("王五",2021);

        ArrayList<Person> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        list.add(p3);

        list.sort(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getId() - o2.getId();
            }
        });

        list.forEach(new Consumer<Person>() {
            @Override
            public void accept(Person person) {
                System.out.println(person);
            }
        });

        System.out.println();
        System.out.println("使用lambda表达式改写:");

        //int compare(T o1, T o2);
        list.sort((o1,o2)-> o1.getId() - o2.getId());
        //public void forEach(Consumer<? super E> action)
        list.forEach((p)-> System.out.println(p));
    }
}

运行结果:

在这里插入图片描述

4.3 Map接口

HashMap 的 forEach**()** 源码**:**

@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
    Node<K,V>[] tab;
    if (action == null)
        throw new NullPointerException();
    if (size > 0 && (tab = table) != null) {
        int mc = modCount;
        for (int i = 0; i < tab.length; ++i) {
            for (Node<K,V> e = tab[i]; e != null; e = e.next)
                action.accept(e.key, e.value);
        }
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }
}

使用示例:

package LambdaDemo;

import java.util.HashMap;
import java.util.function.BiConsumer;

public class Demo6 {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap();

        map.put("张三",19);
        map.put("李四",22);
        map.put("王五",39);
        map.forEach(new BiConsumer() {
            @Override
            public void accept(Object o1, Object o2) {
                System.out.println(o1 +":"+ o2 + "岁了");
            }
        });

        System.out.println("\r\n用lambda表达式改写:");
        map.forEach((o1,o2)->System.out.println(o1 +":"+ o2 + "岁了"));
    }
}

运行结果:
在这里插入图片描述

4.4 结论

优点:

  1. 代码简洁,开发迅速
  2. 方便函数式编程
  3. java引入lambda,方便了集合的一些操作
  4. 非常容易进行并行计算

缺点:

  1. 可读性极差
  2. 不容易调试
  3. 在非并行计算中,效率未必有普通for高

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1264533.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于模块暴露和Hilt的Android模块化方案

ModuleExpose 项目地址&#xff1a;https://github.com/JailedBird/ModuleExpose 序言 Android模块化必须要解决的问题是 如何实现模块间通信 &#xff1f;而模块之间通信往往需要获取相同的实体类和接口&#xff0c;造成部分涉及模块通信的接口和实体类被迫下沉到基础模块&…

使用 Mybatis 的 TypeHandler 存取 Postgresql jsonb 类型

文章目录 使用 TypeHandler 存取 Postgresql jsonb 类型常见错误column "" is of type jsonb but expression is of type character varying 使用 TypeHandler 存取 Postgresql jsonb 类型 首先在数据库表中定义 jsonb 类型&#xff1a; create table tb_user_info…

Unity中Shader的BRDF解析(四)

文章目录 前言一、BRDF 中的 IBL二、解析一下其中的参数1、光照衰减系数 &#xff1a;surfaceReduction2、GI镜面反射在不同角度下的强弱 &#xff1a;gi.specular * FresnelLerp (specColor, grazingTerm, nv);在BRDF中&#xff0c;IBL&#xff08;Image Based Light&#xff…

Shell编程基础 – for循环

Shell编程基础 – for循环 Shell Scripting Essentials - for Loop 大多数编程语言都有循环的概念和语句。如果想重复一个任务数十次&#xff0c;无论是输入数十次&#xff0c;还是输出数十次&#xff0c;对用户来说都不现实。 因此&#xff0c;我们考虑如何用好Bash Shell编…

一个人撸码!之vue3+vite+element-plus后台管理(标签页组件)

一个后台管理常常需要一个标签页来管理已经打开的页面&#xff0c;这里我们单独写一个组件来展示标签页数组。 该标签页组件只做展示不涉及操作数据。标签页数组可记录已打开的数组&#xff0c;还能定义什么页面需要缓存&#xff0c;是一个重要的功能呢。 首先&#xff0c;建立…

【华为OD题库-043】二维伞的雨滴效应-java

题目 普通的伞在二维平面世界中&#xff0c;左右两侧均有一条边&#xff0c;而两侧伞边最下面各有一个伞坠子&#xff0c;雨滴落到伞面&#xff0c;逐步流到伞坠处&#xff0c;会将伞坠的信息携带并落到地面&#xff0c;随着日积月累&#xff0c;地面会呈现伞坠的信息。 1、为了…

FlowJo 10 v10.4(流式细胞分析软件)

FlowJo是一款广泛应用的流式细胞数据分析软件&#xff0c;它功能强大&#xff0c;简单易用&#xff0c;是流式领域最受推荐的一款专业分析软件&#xff0c;也是各高影响力科学期刊使用最多的软件&#xff0c;已经成了行业的一个标准。 FlowJo具有全面专业的分析功能&#xff0…

解析直播第三方美颜SDK:技术原理与应用

时下&#xff0c;直播平台和主播们纷纷引入美颜技术&#xff0c;以提升视觉效果和用户体验。而在众多美颜技术中&#xff0c;直播第三方美颜SDK成为许多开发者和平台的首选&#xff0c;因其灵活性和高效性而备受推崇。 一、技术原理&#xff1a;美颜算法的精髓 第三方美颜SDK…

Keil5 debug

目录 debug调试功能 基本功能&#xff1a; 程序复位&#xff1a;Reset 运行&#xff1a;Run 停止&#xff1a;Stop 断点调试&#xff08;Breakpoint Debugging&#xff09; 单步调试&#xff1a; 单步调试:Step 单步跳过调试&#xff1a;Step Over&#xff1a; 单步返…

不同路径 II(力扣LeetCode)动态规划

不同路径 II 题目描述 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物。…

Centos7安装配置nginx

快捷查看指令 ctrlf 进行搜索会直接定位到需要的知识点和命令讲解&#xff08;如有不正确的地方欢迎各位小伙伴在评论区提意见&#xff0c;小编会及时修改&#xff09; Centos7安装配置nginx Nginx介绍 Nginx (engine x) 是一个高性能的 HTTP 和 反向代理 服务&#xff0c;也…

运营商网络性能测试-Y.1564

前言 在网络部署之后和业务开展之前&#xff0c;运营商迫切希望了解当前网络的性能状态&#xff0c;以便为商业规划和业务推广提供必要的基础数据支持。因此&#xff0c;高可靠性和高精确度的性能测试方法对于运营商评判网络性能的优劣&#xff0c;显得尤为重要&#xff0c;而…

InnoSetupCompiler打包程序

修改默认的安装路径 因为程序可能需要在安装路径中写日志&#xff0c;默认的安装路径C:\Program Files (x86)&#xff0c;这个路径好像是受保护还是啥&#xff0c;如果使用默认的打开会报错。 修改方法&#xff1a; DefaultDirName{autopf}\{#MyAppName} {autopf}改成…

【安卓】安卓xTS之Media模块 学习笔记(1) xTS介绍

1.背景 Media的安卓xTS相关测试和功能修复已经进行了一段时间了。 在此整理总结下xTS工作总结&#xff0c;留待后续查阅整理。 2. xTS介绍 - 什么是xTS 谷歌的xTS是对谷歌发布的CTS/GTS/VTS/STS/BTS/CTS-on-GSI等一系列测试的统称。 因为安卓系统比较庞大&#xff0c;模块多…

.mat格式文件是什么?及将png,jpg,bmp,gif,tiff,psd等格式图片转为.mat格式(附代码)

很多深度学习网络的输入要求为.mat格式&#xff0c;当然也可以直接修改输入数据的代码&#xff0c;比如修改为使用OpenCV读取图片等&#xff0c;但有些网络修改起来比较麻烦&#xff0c;且.mat数据有很多优势&#xff0c;所以部分网络最好还是用默认的.mat格式数据 目录 一、.…

jekins CVE-2018-1000861 漏洞复现

jekins CVE-2018-1000861 漏洞复现 ‍ 名称: jenkins 命令执行 &#xff08;CVE-2018-1000861&#xff09; 描述: ​Jenkins 可以通过其网页界面轻松设置和配置,其中包括即时错误检查和内置帮助。 插件 通过更新中心中的 1000 多个插件,Jenkins 集成了持续集成和持续交付工具…

PTA-6-48 使用面向对象的思想编写程序描述动物

题目&#xff1a; 使用面向对象的思想编写程序描述动物&#xff0c;说明&#xff1a; &#xff08;1) 分析兔子和青蛙的共性&#xff0c;定义抽象的动物类&#xff0c;拥有一些动物共有的属性&#xff1a;名字、颜色、类别&#xff08;哺乳类、非哺乳类&#xff09;&#xff0c…

三十、elasticsearch集群

目录 一、集群的概念 1、节点 2、索引 3、分片和副本 二、集群的架构 三、集群的部署方式 1、单主节点 2、多主节点 3、安全集群 四、搭建ES集群 1、elasticsearch中集群节点有不同的职责划分 2、elasticsearch中的每个节点角色都有自己不同的职责&#xff0c;因此…

中间件安全:JBoss 反序列化命令执行漏洞.(CVE-2017-12149)

中间件安全&#xff1a;JBoss 反序列化命令执行漏洞.&#xff08;CVE-2017-12149&#xff09; JBoss 反序列化漏洞&#xff0c;该漏洞位于 JBoss 的 HttpInvoker 组件中的 ReadOnlyAccessFilter 过滤器中&#xff0c;其 doFilter 方法在没有进行任何安全检查和限制的情况下尝试…