类加载机制与反射

类加载机制与反射

一.虚拟机类加载机制

1.虚拟机类加载机制概述

  • 虚拟机把描述类的数据从class文件加载到内存

  • 将类的数据进行校验,转换解析和初始化

  • 形成可以被java虚拟机直接使用的java类型

2.类加载过程

  • 当程序要使用某个类时,如果该类还未被加载到内存中,系统会通过加载,连接,初始化三步来实现对这个类的加载.

(1)加载

  • 就是指将class文件读入内存,并为之创建一个Class对象.任何类被使用时系统都会建立一个Class对象

(2)链接

  • 验证是否有正确的内部结构,并和其他类协调一致;准备负责为类的静态成员分配内存,并设置默认初始化值解析将类的二进制数据中的符号引用替换为直接引用—> 方便计算机 以后寻址

(3)初始化

  • 在使用时需要初始化

3.类的初始化时机

  • 第一次创建类的实例
  • 类的静态成员使用
  • 类的静态方法调用
  • 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
  • 初始化某个类的子类
  • 直接使用java.exe命令来运行某个主类 —> 主方法运行时 会自动的加载主方法所在的类的字节码文件

二.类加载器

1.类加载器概述

  • 类加载器是负责加载类的对象,将class文件(硬盘)加载到内存中,并为之生成对应的java.lang.Class对象.

(1)例

Hello.class------->类加载器------>Hello.class 
  • Hello:这个类的类对象 (就是Class类的对象)
  • 类对象: 字节码信息形成的对象(包含了这个类中所有的信息) —> 是 Class 类 类型的对象

2.类加载器的分类

(1)分类

类加载器分类描述
Bootstrap ClassLoader引导类是所有加载器的父加载器也被称为根类加载器,负责Java核心类的加载,比如System,String等.
Extension ClassLoader扩展类负责JRE的扩展目录中jar包的加载,在JDK中JRE的lib目录下ext目录.
Application ClassLoade系统类加载自己写的类 ,负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径.
自定义类开发人员可以通过继承java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需求.

(2)继承关系

-Bootstrap ClassLoader
	-Extension ClassLoader
		-Application ClassLoader

3.双亲委派机制

  • 一有事 就找爹 爹做不了的 自己再干

在这里插入图片描述

(1)双亲委派机制描述

  • 指当一个类加载器收到一个类加载请求时,该类加载器首先会把请求委派给父类加载器.每个类加载器都是如此,只有在父类加载器在自己的搜索范围内找不到指定类时,子类加载器才会尝试自己去加载.

(2)双亲委派模型工作过程

a.
  • 当Application ClassLoader 收到一个类加载请求时,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器Extension ClassLoader去完成.
b.
  • 当Extension ClassLoader收到一个类加载请求时,他首先也不会自己去尝试加载这个类,而是将请求委派给父类加载器Bootstrap ClassLoader去完成.
c.
  • 如果Bootstrap ClassLoader加载失败(在<JAVA_HOME>\lib中未找到所需类),就会让Extension ClassLoader尝试加载.
d.
  • 如果Extension ClassLoader也加载失败,就会使用Application ClassLoader加载.
e.
  • 如果Application ClassLoader也加载失败,就会使用自定义加载器去尝试加载.
f.
  • 如果均加载失败,就会抛出ClassNotFoundException异常.

(3)例子

  • 当一个Hello.class这样的文件要被加载时.不考虑我们自定义类加载器,首先会在AppClassLoader中检查是否加载过,如果有那就无需再加载了.如果没有,那么会拿到父加载器,然后调用父加载器的loadClass方法.父类中同理会先检查自己是否已经加载过,如果没有再往上.注意这个过程,直到到达Bootstrap classLoader之前,都是没有哪个加载器自己选择加载的.如果父加载器无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException.

4.CLassLoader类

(1)ClassLoader类概述

  • ClassLoader 叫做类加载器.虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流” 也就是.class字节码文件,这个动作放到java虚拟机外部去实现,以便让应用程序自己决定去如何获取所需要的类,实现这个动作的代模块称之为“类加载器”.

(2)ClassLoader方法

方法描述
static ClassLoader getSystemClassLoader()返回用于委派的系统类加载器
ClassLoader getParent()返回父类加载器进行委派

(3)方法示例

package com.lfg.test;
public class Test02 {
    public static void main(String[] args) {
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        System.out.println(cl);                     //AppClassLoader
        System.out.println(cl.getParent());         //ExtClassLoader
        System.out.println(cl.getParent().getParent());     //null
    }
}

三.反射应用

1.反射机制的概述

  • 反射是指在运行时去获取一个类的变量和方法信息.然后通过获取到的信息来创建对象,调用方法的一种机制.
  • 由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展.

2.获取Class类的对象

(1)描述

  • Class类: Class类型的实例 表示正在运行的java应用程序的类或者接口 类对象.
  • Class类的对象: 想获取和操作类中的内容,首先要获取类的字节码对象(Class类对象),每一个正在运行的类,都有对应的字节码对象,获取了类的字节码对象,就可以使用这个对象的所有方法,这些方法都定义在Class类型中.

(2)示例

a.Student类
package com.lfg.pojo;

import java.util.Objects;

public class Student {

    private String sname;
    private String sgender;
    private int sage;
    public int sid;

    public Student() {
    }

  	private Student(String sname) {
        this.sname = sname;
    }

   	private Student(String sname, String sgender) {
        this.sname = sname;
        this.sgender = sgender;
    }
    
    public Student(String sname, String sgender, int sage) {
        this.sname = sname;
        this.sgender = sgender;
        this.sage = sage;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public String getSgender() {
        return sgender;
    }

    public void setSgender(String sgender) {
        this.sgender = sgender;
    }

    public int getSage() {
        return sage;
    }

    public void setSage(int sage) {
        this.sage = sage;
    }
    
    public int getSid() {
        return sid;
    }

    public void setSid(int sid) {
        this.sid = sid;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return sage == student.sage && Objects.equals(sname, student.sname) && Objects.equals(sgender, student.sgender);
    }

    @Override
    public int hashCode() {
        return Objects.hash(sname, sgender, sage);
    }

    @Override
    public String toString() {
        return "Student{" +
                "sname='" + sname + '\'' +
                ", sgender='" + sgender + '\'' +
                ", sage=" + sage +
                '}';
    }
    
    public void printInfo(){
        toString();
    }
    
    public void prinInfoFamle(String famle){
        System.out.println("famle=>"+famle);
    }
    
    private void pirntInfoName(String sname){
        System.out.println("sname=>"+sname);
    }

    private void pirntInfoPrivate(){
        toString();
    }
}

b.测试类
package com.lfg.test;

import com.lfg.pojo.Student;

public class Test03 {
    public static void main(String[] args) {
        Student student = new Student();
        try {
            //获取Student类的字节码对象
            Class c1 = Student.class;
            Class c2 = student.getClass();
            Class c3 = Class.forName("com.lfg.pojo.Student");
            System.out.println(c1 == c2);
            System.out.println(c2 == c3);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

3.反射获取构造方法

(1)方法

方法描述
Constructor<?>[] getConstructors()返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors()返回所有构造方法对象的数组
Constructor getConstructor(Class<?>… parameterTypes)返回单个公共构造方法对象
Constructor getDeclaredConstructor(Class<?>…parameterTypes)返回单个构造方法对象

(2)Constructor类型

a.描述
  • 表示构造方法类型,这个类的每个对象,都是一个确定的,具体的构造方法
  • 构造方法对象应该具有的功能: 获取构造方法各种信息(构造方法修饰符、构造方法名称、构造方法的参数列表、构造方法的注解),最基本的一个功能就是,创建对象.
b.Constructor类用于创建对象的方法
方法描述
T newInstance(Object…initargs)根据指定的构造方法创建对象,参数为所运行构造方法需要的实际参数.

(3)示例

package com.lfg.test;

import com.lfg.pojo.Student;

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

public class Test04 {
    public static void main(String[] args) {
        Student student = new Student();
        //获取Student类有哪些属性,哪些构造方法,哪些一般方法?

        try {
            //获取Student类的字节码对象
            Class c1 = Student.class;
            Class c2 = student.getClass();
            Class c3 = Class.forName("com.lfg.pojo.Student");

            //获取Student类的公共的构造方法
            Constructor constructor1[] = c3.getConstructors();
            System.out.println(Arrays.toString(constructor1));

            System.out.println("-----------------------------------------");

            //获取Student类所有的构造方法
            Constructor constructor2[] = c3.getDeclaredConstructors();
            System.out.println(Arrays.toString(constructor2));

            System.out.println("-----------------------------------------");

            //获取某公共的无参的构造方法
            Constructor constructor3 = c3.getConstructor();
            System.out.println(constructor3);

            System.out.println("-----------------------------------------");
            //获取某公共的有参的构造方法
            Constructor constructor4 = c3.getConstructor(String.class,String.class,int.class);
            System.out.println(constructor4);

            System.out.println("-----------------------------------------");
            //获取某私有的有参的构造方法
            Constructor constructor5 = c3.getDeclaredConstructor(String.class);
            System.out.println(constructor5);

            System.out.println("-----------------------------------------");
            //使用某公共的无参的构造方法创建对象
            Student stu1 = (Student)constructor3.newInstance();
            stu1.setSname("mary");
            System.out.println(stu1.getSname());

            System.out.println("-----------------------------------------");
            //使用某公共的有参的构造方法创建对象
            Student stu2 = (Student) constructor4.newInstance("范冰冰","female",1);
            System.out.println(stu2.getSname());

            System.out.println("-----------------------------------------");
            //使用某私有的有参的构造方法创建对象
            //使用暴力反射干掉private
            constructor5.setAccessible(true);
            Student stu3 = (Student)constructor5.newInstance("刘仔");
            System.out.println(stu3.getSage()+","+stu3.getSname());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4.反射获取成员变量

(1)方法

方法描述
Field[] getFields()Field[] getFields()返回所有公共成员变量对象的数组
Field[] getDeclaredFields()返回所有成员变量对象的数组
Field getField(String name)返回单个公共成员变量对象
Field getDeclaredField(String name)返回单个成员变量对象
  • Class类获取成员变量对象
  • Field类型
    • 表示:一个成员变量类型,每个对象都是一个具体的成员变量
    • 作用: 获取成员变量的各种信息(修饰符、注解、名称),做各种数据类型的转换
  • Field类用于给成员变量赋值的方法
    • set(Object obj, Object value):用于给obj对象的,该成员变量,赋value值
  • Field类获取成员变量值的方法
    • get(Object obj): 用于获取obj对象的指定成员变量值

(2)示例

package com.lfg.test;

import com.lfg.pojo.Student;

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

public class Test05 {
    public static void main(String[] args) {
        Student student = new Student();
        //获取Student类有哪些属性,哪些构造方法,哪些一般方法?

        try {
            //获取Student类的字节码对象
            Class c1 = Student.class;
            Class c2 = student.getClass();
            Class c3 = Class.forName("com.lfg.pojo.Student");

            //获取Student类的公共的成员变量
            Field field1[] = c3.getFields();
            System.out.println(Arrays.toString(field1));
            System.out.println("-----------------------------------");

            //获取Student类所有的成员变量
            Field field2[] = c3.getDeclaredFields();
            System.out.println(Arrays.toString(field2));
            System.out.println("-----------------------------------");

            //获取Student类的某公共的成员变量
            Field field3 = c3.getField("sid");
            System.out.println(field3);
            System.out.println("-----------------------------------");

            //获取Student类的某私有的成员变量
            Field field4 = c3.getDeclaredField("sname");
            System.out.println(field4);
            System.out.println("-----------------------------------");

            //使用Student类的某公共的成员变量
            field3.set(student,1);  //student.setSid(1);
            System.out.println(field3.get(student)); //student.getSid()

            System.out.println("-----------------------------------");
            //使用Student类的某私有的成员变量
            field4.setAccessible(true);
            field4.set(student,"蔡坤");
            System.out.println(field4.get(student));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5.获取类中的成员方法

(1)方法

方法描述
Method[] getMethods()返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的
Method getMethod(String methodName, Class<?>…parameterTypes)返回单个公共成员方法对象
Method getDeclaredMethod(String methodName, Class<?>…parameterTypes)返回单个成员方法对象
  • Class类获取成员方法对象
  • Method类型
    • 表示:成员方法的类型,该类型的每个对象,都是一个具体的成员方法
    • 作用:获取成员方法信息,运行方法
  • Method类用于执行方法的功能
    • invoke(Object obj, Object…values)
      • 调用obj对象的成员方法
      • 参数是values
      • 返回值是Object类型

(2)示例

package com.lfg.test;

import com.lfg.pojo.Student;

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

public class Test06 {
    public static void main(String[] args) {
        Student student = new Student();
        //获取Student类有哪些属性,哪些构造方法,哪些一般方法?

        try {
            //获取Student类的字节码对象
            Class c1 = Student.class;
            Class c2 = student.getClass();
            Class c3 = Class.forName("com.lfg.pojo.Student");

            //获取Student类的公共的成员方法(包括继承来的)
            Method method1[] = c3.getMethods();
            System.out.println(Arrays.toString(method1));
            System.out.println("---------------------------------");

            //获取Student类的所有的成员方法
            Method method2[] = c3.getDeclaredMethods();
            System.out.println(Arrays.toString(method2));
            System.out.println("---------------------------------");

            //获取Student类的某公共的成员方法
            Method method3 = c3.getMethod("printInfo");
            System.out.println(method3);
            System.out.println("---------------------------------");

            //获取Student类的某私有的成员方法
            Method method4 = c3.getDeclaredMethod("pirntInfoPrivate");
            System.out.println(method4);
            System.out.println("---------------------------------");

            //使用Student类的某公共的成员方法
            method3.invoke(student);  //student.eat();
            System.out.println("---------------------------------");

            //使用Student类的某私有的成员方法
            method4.setAccessible(true);
            method4.invoke(student);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6.暴力反射

(1)概述

  • 通过Class类中getDeclaredXXX方法以获取类中的所有声明的成员(属性、方法、构造),私有的成员也可以获取到.但是私有成员进行访问使用时,会因为权限问题导致失败,因此就需要暴力反射解决访问私有的问题

(2)修改对象的访问权限

  • AccessibleObject类是Field,Method和Constructor对象的基类. 它提供了将反射对象标记为在使用它时抑制默认Java语言访问控制检查的功能.
  • setAccessible(boolean flag)
    • true的值表示反射对象应该在使用时抑制Java语言访问检查
    • false的值表示反映的对象应该强制执行Java语言访问检查
  • 一旦设定当前对象可以访问,私有的成员也可以被访问,被修改

四.反射实现多方法请求

1.BaseServlet

package com.lfg.servlet;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class BaseServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        String flag = req.getParameter("flag");
        //获取当前类的字节码对象
        Class clazz = this.getClass();
        try {
            //flag其实就是要执行的方法的名字
            //所有需要执行的方法的参数都是request和response
            //根据方法名及其参数的数据类型获取要执行的方法
            Method method = clazz.getDeclaredMethod(flag,HttpServletRequest.class,HttpServletResponse.class);
            method.setAccessible(true);
            method.invoke(this,req,resp);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

2.使用

  • 使用要求:
    • 前端必须传递flag数据,且该数据的值必须和servlet中要执行的方法名字一致
    • servlet中所有需要执行的方法的参数必须是request和response
public class XxxServlet extends BaseServlet{
	
}

五.分页示例

1.分页概述

  • 当前页页码:page

  • 每页显示数据条数:rows

  • 从哪一条开始取(偏移量):index = (page-1)*rows

  • 数据总条数:countRows

  • 总页数:countPages

  • 上一页页码:prevPage,如果当前页是第一页,需要判断

  • 下一页页码:nextPage,如果当前页是最后一页,需要判断

2.PageUtil工具类

package com.lfg.utils;

public class PageUtil {

    private int page;      //当前页页码
    private int rows;       //每页显示条数
    private int index;      //偏移量
    private int countRows;      //总条数
    private int countPages;     //总页数
    private int prevPage;       //当前页的上一页页码
    private int nextPage;       //当前页的下一页页码

    public PageUtil(String page,int rows,int countRows){
        init_page(page);
        this.rows = rows;
        init_index();
        this.countRows = countRows;
        init_countPages();
        init_prevPage();
        init_nextPage();
    }

    private void init_page(String page){
        if (page == null || "".equals(page)) {
            this.page = 1;
        } else {
            this.page = Integer.parseInt(page);
        }
    }

    private void init_index(){
        this.index = (this.page - 1) * this.rows;
    }

    private void init_countPages(){
        int mod = this.countRows % this.rows;
        if (mod == 0) {
            this.countPages = this.countRows / this.rows;
        } else {
            this.countPages = this.countRows / this.rows + 1;
        }
    }

    private void init_prevPage(){
        if (this.page == 1) {
            this.prevPage = 1;
        } else {
            this.prevPage = this.page - 1;
        }
    }

    private void init_nextPage(){
        if (this.page == this.countPages) {
            this.nextPage = this.countPages;
        } else {
            this.nextPage = this.page + 1;
        }
    }

    public int getPage() {
        return page;
    }

    public int getRows() {
        return rows;
    }

    public int getIndex() {
        return index;
    }

    public int getCountRows() {
        return countRows;
    }

    public int getCountPages() {
        return countPages;
    }

    public int getPrevPage() {
        return prevPage;
    }

    public int getNextPage() {
        return nextPage;
    }
}

3.index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    恭喜您,登录成功<br>
    <a href="studentServlet?flag=getStudentByPage&page=1">展示学生信息</a>
</body>
</html>

4.Dao层

(1)StudentDao

    int getCountRows();
    List<Student> getStudentByPage(PageUtil pageUtil);

(2)StudentDaoImpl

    @Override
    public int getCountRows() {
        int countRows = 0;
        String sql = "select count(*) from student";
        try {
            countRows = (int)(long)queryRunner.query(sql, new ScalarHandler());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return countRows;
    }

    @Override
    public List<Student> getStudentByPage(PageUtil pageUtil) {
        List<Student> list = null;
        String sql = "select * from student limit ?,?";
        try {
            list = queryRunner.query(sql, new BeanListHandler<>(Student.class),pageUtil.getIndex(),pageUtil.getRows());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }

5.Service层

(1)StudentService

    int getCountRows();
    List<Student> getStudentByPage(PageUtil pageUtil);

(2)StudentServiceImpl

    @Override
    public int getCountRows() {
        return studentDao.getCountRows();
    }

    @Override
    public List<Student> getStudentByPage(PageUtil pageUtil) {
        return studentDao.getStudentByPage(pageUtil);
    }

6.StudentServlet

    protected void getStudentByPage(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        //分页数据查询
        String page = req.getParameter("page");
        int rows = 10;
        int countRows = studentService.getCountRows();
        PageUtil pageUtil = new PageUtil(page, rows, countRows);
        List<Student> list = studentService.getStudentByPage(pageUtil);
        req.setAttribute("stuList",list);
        req.setAttribute("pageUtil",pageUtil);
        req.getRequestDispatcher("student.jsp").forward(req,resp);
    }

7.Student.jsp

在这里插入图片描述

六.挂载图片

1.学生表添加头像列

ALTER TABLE student ADD sphoto VARCHAR(50);

2.修改实体类

private String sphoto;

3.挂载图片

在这里插入图片描述

4.测试挂载是否成功

在这里插入图片描述

5.完善student.jsp内容

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WEB渗透—PHP反序列化(一)

Web渗透—PHP反序列化 课程学习分享&#xff08;课程非本人制作&#xff0c;仅提供学习分享&#xff09; 靶场下载地址&#xff1a;GitHub - mcc0624/php_ser_Class: php反序列化靶场课程&#xff0c;基于课程制作的靶场 课程地址&#xff1a;PHP反序列化漏洞学习_哔哩…

Datawhale聪明办法学Python(task2Getting Started)

一、课程基本结构 课程开源地址&#xff1a;课程简介 - 聪明办法学 Python 第二版 章节结构&#xff1a; Chapter 0 安装 InstallationChapter 1 启航 Getting StartedChapter 2 数据类型和操作 Data Types and OperatorsChapter 3 变量与函数 Variables and FunctionsChapte…

手拉手探索JSONCrack数据可视化

JSON Crack数据可视化工具 官网&#xff1a;https://jsoncrack.com/ 项目地址&#xff1a;https://github.com/AykutSarac/jsoncrack.com SON Crack 是一个很方便的 JSON 数据可视化工具。 该项目不是简单的展示 JSON 数据,而是将其转化为类似思维导图的形式,支持放大/缩小、展…

华为或荣耀手机禁止强制升级鸿蒙系统的终极方法

需要有数据传输的usb线.打开usb调试模式. 进这个链接下载华为ADB一键卸载VS重装软件 按里面的视频说明,输入88 然后回车即可 https://download.csdn.net/download/viqecel/12161462

Course2-Week4-决策树

Course2-Week4-决策树 文章目录 Course2-Week4-决策树1. 决策树的直观理解2. 构建单个决策树2.1 熵和信息增益2.2 构建决策树——二元输入特征2.3 构建决策树——多元输入特征2.4 构建决策树——连续的输入特征2.5 构建回归树——连续的输出结果(选修)2.6 代码实现-递归构建单个…

数据库范式(详细介绍)

目录 第一范式&#xff08;原子性&#xff09; 第二范式&#xff08;主键唯一性&#xff09; 第三范式&#xff08;原子性主键唯一性&#xff09; BC范式(3NFplus) 第一范式&#xff08;原子性&#xff09; 确保每列保证原子性&#xff0c;保证这个属性&#xff08;字段&am…

未来智能座舱中的人机交互

智能车辆人机交互的发展是中国智能车辆企业品牌升级的重要突破点。通过不断整合人与车辆之间的相互作用&#xff0c;未来的智能车辆将能够提供更全面的沉浸式体验&#xff0c;推动新的互动方式和技术的成熟。这些交互技术不仅满足基本的安全需求&#xff0c;还能满足更深层次的…

马赛克,克星,真来了!v2.0

大家好&#xff0c;今天继续聊聊 AI 开源项目 AI 开源项目 1、DemoFusion AI 绘画的潜力还没有充分挖掘出来&#xff0c;仍然还有上升的空间。 DemoFusion 就是这么一个开源项目&#xff0c;继续深挖了 AI 绘画在高分辨率图片生成的效果。 提高分辨率&#xff0c;马赛克&a…

【JUC】二十五、ThreadLocal内存泄漏问题(强软弱虚四种引用)

文章目录 1、引用之强软弱虚2、强引用3、软引用4、弱引用5、虚引用6、ThreadLocal回顾7、ThreadLocal使用弱引用的原因8、清除脏Entry9、最佳实践 不再会被使用的对象或者变量占用的内存不能被回收&#xff0c;就是内存泄露&#xff08;累积可能导致OOM&#xff09;。 1、引用之…

Echarts小问题汇总

文章目录 Echarts小问题汇总1.柱状图第一条柱子遮挡Y轴解决方法2.在大屏渲染后 拖到小屏变模糊3.相邻柱状图中间不要有空隙4.实现echarts图表自适应5.单个柱状图最大宽度 Echarts小问题汇总 记录工作中使用Echarts的遇见的一些小问题&#xff0c;后续会不断进行补充 1.柱状图…

三数之和(LeetCode 15)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路方法一&#xff1a;暴力法方法二&#xff1a;排序双指针 5.实现示例参考文献 1.问题描述 给你一个整数数组 nums&#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时…

P1单片机定时器配置及定时器中断——C51(超详细)

目录 1. 简介 1.1 概念解读 1.2 定时器怎么定时 1.什么是晶振 2.什么是时钟周期 3.什么是机器周期 4.加1经过了多少时间 1.3 定时器编程 1.如何算出10ms定时器的初值(TL0 TH0) 2.关于TCON ,怎么知道爆表 3.怎么开始计时(TR0) 4.定时器使用是有很多种模式的&#xf…

Gerrit的使用

项目存储配置 为了能够模拟开发人员和审核人员两个角色&#xff0c;需要有1台服务器模拟操作提交和审核 登陆linux服务器账户&#xff0c;并生成id_rsa.pub 添加git配置 Git配置一般存储的是name 和 email地址 这里的email地址需要和gerrit系统的账号的email地址一致&#…

佛山陶企再造行业新风口,开启中国陶瓷下半场

近年来&#xff0c;消费形态逐渐呈现年轻化、时尚化、数字化的趋势&#xff0c;新一地居住者对于居住环境的品质和舒适度要求日益提高。伴随着新消费势力的崛起&#xff0c;家居建材行业消费转型升级已成必然。“千年陶都”佛山作为我国陶瓷行业的风向标&#xff0c;率先推进技…

SD-WAN组网案例分享——简单高效的远程视频监控方案

在网络化和信息化建设的推动下&#xff0c;远程视频监控设备的应用范围已经不再局限于政府部门和金融行业。中小企业对远程视频监控设备的需求也在持续增长。 案例背景 本次案例分享的是一家大型制造业企业&#xff0c;该企业拥有遍布全国各地的生产厂房和仓库。然而&#xff…

GPS定位与IP地址定位的差异及应用场景

随着科技的不断发展&#xff0c;定位技术在日常生活和商业应用中变得越来越普遍。在定位技术中&#xff0c;GPS&#xff08;全球定位系统&#xff09;和IP地址定位是两种常见的方法。本文将探讨GPS定位与IP地址定位的差异以及它们在不同应用场景中的应用。 1. GPS定位 a. 工作…

flink-1.17.2的单节点部署

flink 简介 Apache Flink 是一个开源的流处理和批处理框架&#xff0c;用于大数据处理和分析。它旨在以实时和批处理模式高效处理大量数据。Flink 支持事件时间处理、精确一次语义、有状态计算等关键功能。 以下是与Apache Flink相关的一些主要特性和概念&#xff1a; 流处理…

故障注入测试有哪些多重作用?

在软件开发的世界中&#xff0c;保证系统的鲁棒性和稳定性至关重要。为了应对各种潜在的故障和异常情况&#xff0c;测试团队采用了各种测试方法&#xff0c;其中之一就是故障注入测试。这种测试方法的目标是有目的地向系统引入故障&#xff0c;以评估系统在面对异常情况时的表…

响应式编程一之基础夯实(初学必看!)

响应式编程一之基础夯实&#xff08;初学必看&#xff01;&#xff09; 函数式编程常见lambda表达式求一个数组里面的最小值代码简洁的函数式编程返回指定对象的接口实例JDK8 新特性jdk8函数式接口predicate 判断hashmap是否为空consumer总结方法引用示例lambda表达式的类型推断…

解题方式篇-回溯

回溯算法 1、简介 简介&#xff1a;回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。 回溯是递归的副产品&#xff0c;只要有递归就会有回溯。回溯是一种暴力的搜索方式。 回溯法&#xff0c;一般可以解决如下几种问题&#xff1a;组合&#xff08;无序&#xff0…