八股之Java基础

news2024/11/13 19:41:42

注:本文部分内容源自Java 面试指南 | JavaGuide

一、基础概念与常识

1.JVM、JDK、JRE

JVM:Java Virtual Machine,虚拟机,运行Java字节码,实现Java的平台无关性

JDK:Java Development Kit,Java开发工具包,能够创建和编译 Java 程序。它包含了 JRE,同时还包含了编译 java 源码的编译器 javac 以及一些其他工具比如 javadoc(文档注释工具)、jdb(调试器)、jconsole(基于 JMX 的可视化监控⼯具)、javap(反编译工具)等

JRE:Java Runtime Environment,是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,主要包括 Java 虚拟机(JVM)、Java 基础类库(Class Library)

二、数据类型

1.基本数据类型

byte、short、int、long、float、double、char(2字节)、boolean

对应的包装类:Byte、Short、Integer、Long、Float、Double、Character、Boolean

2.基本类型和包装类型的区别

用途:除了定义一些常量和局部变量之外,在其他地方比如方法参数、对象属性中很少会使用基本类型。并且包装类型可用于泛型

存储方式:基本数据类型的局部变量存放在栈中的局部变量表中,成员变量(未被 static 修饰 )存放在堆中。包装类型属于对象类型,存放在堆中

占用空间:相比于包装类型(对象类型), 基本数据类型占用的空间往往非常小

默认值:成员变量包装类型不赋值就是 null ,而基本类型有默认值且不是 null

比较方式:对于基本数据类型来说,== 比较的是值。对于包装数据类型来说,== 比较的是对象的内存地址。所有整型包装类对象之间值的比较,全部使用 equals() 方法

3.自动装箱与拆箱

装箱其实就是调用了包装类的valueOf()方法,拆箱其实就是调用了 xxxValue()方法

频繁拆装箱会严重影响系统的性能,应尽量避免不必要的拆装箱操作

private static long sum() {
    // 应该使用 long 而不是 Long
    Long sum = 0L;
    for (long i = 0; i <= Integer.MAX_VALUE; i++)
        sum += i;
    return sum;
}

4.包装类型的缓存机制

Java 基本数据类型的包装类型的大部分都用到了缓存机制来提升性能。

Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False,Float和Double没有实现缓存机制

Interger缓存源码:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}
private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static {
        // high value may be configured by property
        int h = 127;
    }
}
Integer i1 = 40;  // 等价于 Integer i1=Integer.valueOf(40)
Integer i2 = new Integer(40);
System.out.println(i1==i2);  // 输出false

三、变量

1.为什么成员变量要赋默认值

安全性:如果没有默认值,成员变量将包含内存中的任意随机数据。这会导致程序在读取这些变量时出现不可预知的行为,可能引发难以调试的错误

局部变量未赋值编译报错,而成员变量赋值可能在运行时发生,难以检测

四、方法

1.重载与重写的区别

重载发生在编译期,是同一个类中多个同名方法根据不同参数列表来执行不同的逻辑处理

重写发生在运行期,是子类对父类允许访问的方法的实现过程进行重新编写

重写要求:

  • 方法名相同、形参列表相同
  • 返回值类型与父类相同或是其子类,方法声明抛出的异常类应比父类更小或相等
  • 访问权限应比父类方法的访问权限更大或相等

2.Java有引用传递吗

Java 中将实参传递给方法的方式是 值传递

  • 如果参数是基本类型的话,传递的是基本类型的字面量值的拷贝,会创建副本。
  • 如果参数是引用类型,传递的是实参所引用的对象在堆中地址值的拷贝,同样也会创建副本

五、面向对象

1.接口和抽象类

  • 设计目的:接口主要用于对类的行为进行约束,抽象类主要用于代码复用,强调所属关系
  • 继承和实现:一个类只能继承一个类,可以实现多个接口,一个接口也可以继承多个其他接口
  • 成员变量:接口中的成员变量只能是 public static final 类型的,抽象类的成员变量可以有任何修饰符(private, protected, public),可以在子类中被重新定义或赋值
  • 方法
    • Java 8 之前,接口中的方法默认是 public abstract ,也就是只能有方法声明。自 Java 8 起,可以在接口中定义 default(默认) 方法和 static (静态)方法。 自 Java 9 起,接口可以包含 private 方法
    • 抽象类可以包含抽象方法和非抽象方法。抽象方法没有方法体,必须在子类中实现。非抽象方法有具体实现,可以直接在抽象类中使用或在子类中重写

2.引用拷贝、浅拷贝和深拷贝

// 假设有一个简单的类
class MyObject {
    int value;
    SubObject subObject;
}

MyObject originalObject = new MyObject();

// 引用拷贝
MyObject copy = originalObject;

// 浅拷贝:只拷贝了顶层对象,内部的 SubObject 仍然是引用拷贝
// clone()是Object类提供的方法
MyObject shallowCopy = originalObject.clone();

// 深拷贝:需要手动实现,递归地拷贝所有引用类型成员
MyObject deepCopy = new MyObject();
deepCopy.value = originalObject.value;
deepCopy.subObject = new SubObject(originalObject.subObject);

3.Object类常见方法

/**
 * native 方法,用于返回当前运行时对象的 Class 对象,使用了 final 关键字修饰,故不允许子类重写。
 */
public final native Class<?> getClass()
/**
 * native 方法,用于返回对象的哈希码,主要使用在哈希表中,比如 JDK 中的HashMap。
 */
public native int hashCode()
/**
 * 用于比较 2 个对象的内存地址是否相等,String 类对该方法进行了重写以用于比较字符串的值是否相等。
 */
public boolean equals(Object obj)
/**
 * native 方法,用于创建并返回当前对象的一份拷贝。
 */
protected native Object clone() throws CloneNotSupportedException
/**
 * 返回类的名字实例的哈希码的 16 进制的字符串。建议 Object 所有的子类都重写这个方法。
 */
public String toString()
/**
 * native 方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。
 */
public final native void notify()
/**
 * native 方法,并且不能重写。跟 notify 一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。
 */
public final native void notifyAll()
/**
 * native方法,并且不能重写。暂停线程的执行。注意:sleep 方法没有释放锁,而 wait 方法释放了锁 ,timeout 是等待时间。
 */
public final native void wait(long timeout) throws InterruptedException
/**
 * 多了 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 纳秒。。
 */
public final void wait(long timeout, int nanos) throws InterruptedException
/**
 * 跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念
 */
public final void wait() throws InterruptedException
/**
 * 实例被垃圾回收器回收的时候触发的操作
 */
protected void finalize() throws Throwable { }

4.==、equals()、hashCode()

==:比较基本数据类型的值,引用数据类型的内存地址

equals():类没有重写该方法则等价于“==”,一般重写为比较对象内容是否相等

hashCode():如果需要把对象放入哈希表(HashSet、HashMap)中需要重写,否则该方法无用

六、String

1.String、StringBuffer和StringBuilder

可变性:String不可变

线程安全性:String为常量,StringBuffer方法中有同步锁,StringBuilder线程不安全

性能:String改变时会生成新的对象,StringBuffer、StringBuilder修改自身(前者有同步锁性能略低)

使用场景:

  • 操作少量的数据: 适用 String
  • 单线程操作字符串缓冲区下操作大量数据: 适用 StringBuilder
  • 多线程操作字符串缓冲区下操作大量数据: 适用 StringBuffer

2.为什么String是不可变的

  1. 保存字符串的数组被 final 修饰且为私有的,并且String 类没有提供/暴露修改这个字符串的方法。
  2. String 类被 final 修饰导致其不能被继承,进而避免了子类破坏 String 不可变

3.字符串常量池

字符串常量池 是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建

4.String s1 = new String("abc");这句话创建了几个字符串对象?

如果字符串常量池中不存在字符串对象“abc”的引用,那么它会在堆上创建两个字符串对象,其中一个字符串对象的引用会被保存在字符串常量池中,反之会创建一个字符串对象

5.intern()方法

String.intern() 是一个 native(本地)方法,其作用是将指定的字符串对象的引用保存在字符串常量池中

// 在堆中创建字符串对象”Java“
// 将字符串对象”Java“的引用保存在字符串常量池中
String s1 = "Java";
// 直接返回字符串常量池中字符串对象”Java“对应的引用
String s2 = s1.intern();
// 会在堆中在单独创建一个字符串对象,不会放入常量池
String s3 = new String("Java");
// 直接返回字符串常量池中字符串对象”Java“对应的引用
String s4 = s3.intern();
// s1 和 s2 指向的是堆中的同一个对象
System.out.println(s1 == s2); // true
// s3 和 s4 指向的是堆中不同的对象
System.out.println(s3 == s4); // false
// s1 和 s4 指向的是堆中的同一个对象
System.out.println(s1 == s4); //true

6.String 类型的变量和常量做“+”运算时发生了什么?

对于编译期可以确定值的字符串,也就是常量字符串 ,jvm 会将其存入字符串常量池。并且,字符串常量拼接得到的字符串常量在编译阶段就已经被存入字符串常量池,这个得益于编译器的优化

字符串不加 final 关键字拼接时,编译器视作变量,实际运算是

String str3 = new StringBuilder().append(str1).append(str2).toString();

字符串不加 final 关键字拼接时,编译器视作常量,直接进行字符串拼接并存入常量池

七、异常

1.异常分类

  • Exception :程序本身可以处理的异常,可以通过 catch 来进行捕获
  • ErrorError 属于程序无法处理的错误 ,不建议通过catch捕获

Checked Exception 即 受检查异常 ,Java 代码在编译过程中,如果受检查异常没有被 catch或者throws 关键字处理的话,就没办法通过编译

Unchecked Exception不受检查异常 ,Java 代码在编译过程中 ,我们即使不处理不受检查异常也可以正常通过编译

RuntimeException 及其子类都统称为非受检查异常,常见的有:

  • NullPointerException(空指针错误)
  • IllegalArgumentException(参数错误比如方法入参类型错误)
  • NumberFormatException(字符串转换为数字格式错误,IllegalArgumentException的子类)
  • ArrayIndexOutOfBoundsException(数组越界错误)
  • ClassCastException(类型转换错误)
  • ArithmeticException(算术错误)
  • SecurityException (安全错误比如权限不够)
  • UnsupportedOperationException(不支持的操作错误比如重复创建同一用户)

2.Throwable类常用方法

  • String getMessage(): 返回异常发生时的简要描述
  • String toString(): 返回异常发生时的详细信息
  • String getLocalizedMessage(): 返回异常对象的本地化信息。使用 Throwable 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 getMessage()返回的结果相同
  • void printStackTrace(): 在控制台上打印 Throwable 对象封装的异常信息

3.try-catch-finally

  • try块:用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally
  • catch块:用于处理 try 捕获到的异常
  • finally 块:无论是否捕获或处理异常,finally 块里的语句都会被执行。当在 try 块或 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行

面对必须要关闭的资源,应该优先使用 try-with-resources 而不是try-finally。随之产生的代码更简短,更清晰,产生的异常对我们也更有用

try (BufferedInputStream bin = new BufferedInputStream(new FileInputStream(new File("test.txt")));
     BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(new File("out.txt")))) {
    int b;
    while ((b = bin.read()) != -1) {
        bout.write(b);
    }
}
catch (IOException e) {
    e.printStackTrace();
}

八、泛型

1.泛型介绍

泛型一般有三种:泛型类泛型接口泛型方法

// 泛型类
public class Generic<T>{
    private T key;
    // 泛型方法
    public static < E > void printArray( E[] inputArray )
    {
        for ( E element : inputArray ){
            System.out.printf( "%s ", element );
        }
        System.out.println();
    }
}
// 泛型接口
public interface Generator<T> {
    public T method();
}

注意: public static < E > void printArray( E[] inputArray ) 一般被称为静态泛型方法;在 java 中泛型只是一个占位符,必须在传递类型后才能使用。类在实例化时才能真正的传递类型参数,由于静态方法的加载先于类的实例化,也就是说类中的泛型还没有传递真正的类型参数,静态的方法的加载就已经完成了,所以静态泛型方法无法使用类上声明的泛型

2.项目中哪里用到了泛型

九、反射

1.动态代理的实现

public class DebugInvocationHandler implements InvocationHandler {
    /**
     * 代理类中的真实对象
     */
    private final Object target;

    public DebugInvocationHandler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
        System.out.println("before method " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("after method " + method.getName());
        return result;
    }
}

2.反射的优缺点

优点:可以动态的创建和使用对象,代码更加灵活、为各种框架提供开箱即用的功能提供了便利

缺点:增加了安全问题。比如可以无视泛型参数的安全检查(泛型参数的安全检查发生在编译时)。另外,反射基本是解释执行,性能稍差,不过对于框架来说影响不大

3.反射相关API

// 获取 Class 对象的四种方法
Class alunbarClass = TargetObject.class;

Class alunbarClass1 = Class.forName("cn.javaguide.TargetObject");  // 全类名

TargetObject o = new TargetObject();
Class alunbarClass2 = o.getClass();

Class alunbarClass3 = ClassLoader.getSystemClassLoader().loadClass("cn.javaguide.TargetObject");

// 获取类的信息
String packageName = alunbarClass.getPackage().getName();  // 包名
String fullClassPath = alunbarClass.getName();  // 全类名

TargetObject targetObiect = alunbarClass.newInstance();  // 创建对象实例

Field field = alunbarClass.getField(fieldName);  // 根据属性名获取public属性
Field[] fields = alunbarClass.getFields();  // 获取所有属性
Field field = alunbarClass.getDeclaredField(fieldName);  // 根据属性名获取任意权限的属性
field.setAccessible(true);  // 取消安全检查,即使field是私有的也可以访问
field.getName();  // 获取属性名
field.get(targetObject);  // 获取targetObject实例对象中field属性的属性值
field.set(targetObject, fieldValue);  // 为targetObject实例对象中field属性赋值

// Method、Constructor类与Field类相关操作基本相同
// 执行method方法
// 如果方法有返回值,统一返回Object,但运行类型与方法定义的返回类型一致
method.invoke(targetObject, args1, args2);  

十、注解

1.注解如何生效

注解只有被解析之后才会生效,常见的解析方法有两种:

  • 编译期直接扫描:编译器在编译 Java 代码的时候扫描对应的注解并处理,比如某个方法使用@Override 注解,编译器在编译的时候就会检测当前的方法是否重写了父类对应的方法。
  • 运行期通过反射处理:像框架中自带的注解(比如 Spring 框架的 @Value@Component)都是通过反射来进行处理的。

十一、序列化和反序列化

  • 序列化:将数据结构或对象转换成二进制字节流的过程
  • 反序列化:将在序列化过程中所生成的二进制字节流转换成数据结构或者对象的过程

序列化的主要目的是通过网络传输对象或者说是将对象存储到文件系统、数据库、内存中

1.JDK 自带的序列化方式

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
@ToString
// 只需实现 Serializable 接口
public class RpcRequest implements Serializable {
    private static final long serialVersionUID = 1905122041950251207L;
    private String requestId;
    private String interfaceName;
    private String methodName;
    private Object[] parameters;
    private Class<?>[] paramTypes;
    private RpcMessageTypeEnum rpcMessageTypeEnum;
}

序列化号 serialVersionUID 用于版本控制。反序列化时,会检查 serialVersionUID 是否和当前类的 serialVersionUID 一致。若不一致会抛出 InvalidClassException 异常

强烈推荐每个序列化类都手动指定其 serialVersionUID(需要使用 static 和 final 关键字

2.如果有些字段不想序列化怎么办?

使用 transient 关键字修饰,阻止变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。

  • transient 只能修饰变量,不能修饰类和方法
  • transient 修饰的变量,在反序列化后变量值将会被置成类型的默认值
  • static 变量因为不属于任何对象(Object),所以无论有没有 transient 关键字修饰,均不会被序列化

3.为什么不推荐使用 JDK 自带的序列化?

  • 不支持跨语言调用 : 如果调用的是其他语言开发的服务的时候就不支持了
  • 性能差:主要原因是序列化之后的字节数组体积较大,导致传输成本加大
  • 存在安全问题:序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码

十二、I/O

Java IO 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的。

  • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流

1.I/O流为什么要划分字节流和字符流

问题本质是:不管是文件读写还是网络发送接收,信息的最小存储单元都是字节,那为什么 I/O 流操作要分为字节流操作和字符流操作呢?

主要有两点原因:

  • 字符流是由 Java 虚拟机将字节转换得到的,这个过程还算是比较耗时
  • 如果我们不知道编码类型的话,使用字节流的过程中很容易出现乱码问题

2.Java I/O 中的设计模式有哪些

十三、语法糖

1.常见语法糖

泛型、自动拆装箱、变长参数、枚举、内部类、增强 for 循环、try-with-resources 语法、lambda 表达式

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

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

相关文章

PwnLab: init-文件包含、shell反弹、提权--靶机渗透思路讲解

Vulnhub靶机链接回【PwnLab】 首页有一个登录框 image-20240807124822770 他没有验证码&#xff0c;我们试试暴力破解 image-20240807122743025 开始爆破了&#xff0c;全部失败&#xff0c;哈哈哈 image-20240807122851001 nmap全端口扫描试试 image-20240807131408315 有…

无法访问jakarta.servlet.http.HttpServletRequest

1、问题 无法访问jakarta.servlet.http.HttpServletRequest2、原因 JDK1.8升级到高版本后&#xff0c;需要手动引入jakarta.servlet-api 3、解决 增加依赖 <dependency><groupId>jakarta.servlet</groupId><artifactId>jakarta.servlet-api</ar…

6.2.面向对象技术-UML图

UML UML事物关系依赖关联聚合组合 泛化实现 类图对象图用例图序列图通信图状态图活动图构件图部署图练习题 UML 上午选择题3-4分&#xff0c;下午案例分析必考 UML是统一建模语言&#xff0c;和程序设计语言并无关系。 UML三个要素&#xff1a;UML的基本构造块、支配这些构造…

代码随想录算法训练营第二十一天 | 77. 组合, 216.组合总和III , 17.电话号码的字母组合

目录 77. 组合 思路 回溯法三部曲 方法一&#xff1a; 回溯未剪枝 方法二&#xff1a;回溯剪枝 心得收获 216.组合总和III 思路 方法一&#xff1a;回溯-没有使用sum来统计path里元素的总和 方法二&#xff1a;回溯&#xff0c;使用sum来保存当前路径上的总和 心得…

如何应用OceanBase 的实时SQL诊断,解决AP场景下的痛点

随着数据量的快速增长与用户需求的变化&#xff0c;数据库的管理与优化工作日益凸显其重要性。作为DBA及开发者&#xff0c;您是否曾面临以下挑战&#xff1a; ○ 分析场景下&#xff0c;在处理大规模数据的且耗时较长的查询是&#xff0c;常涉及海量数据的处理及复杂的计算&…

Python 设计模式之工厂函数模式

文章目录 案例基本案例逐渐复杂的案例 问题回顾什么是工厂模式&#xff1f;为什么会用到工厂函数模式&#xff1f;工厂函数模式和抽象工厂模式有什么关系&#xff1f; 工厂函数模式是一种创建型设计模式&#xff0c;抛出问题&#xff1a; 什么是工厂函数模式&#xff1f;为什么…

Vue3学习笔记第一天

MVVM Vue是一种用于构建用户界面的JavaScript框架。MVVM 是Vue采用的一种软件架构模式&#xff0c;用于构建交互式的用户界面。它的全称是 Model-View-ViewModel&#xff0c;这三个部分分别代表了应用程序的不同层次和角色&#xff1a; Model&#xff08;模型&#xff09;&…

【ARM】v8架构programmer guide(3)_ARMv8的寄存器

目录 4.ARMv8 registers 4.1 AArch64 特殊寄存器 4.1.1 Zero register 4.1.2 Stack pointer &#xff08;SP) 4.1.3 Program Counter &#xff08;PC) 4.1.4 Exception Link Register(ELR) 4.1.5 Saved Process Status Register &#xff08;SPSR&#xff09; 4.2 Proc…

性能测试基础概念

前言&#x1f440;~ 上一章我们介绍了单元测试Junit的使用&#xff0c;今天我们来讲解一下性能测试的一些基础概念为后面我们进行性能测试做铺垫 什么是性能测试&#xff1f; 性能测试和功能测试有什么区别&#xff1f; 影响一个软件性能因素有哪些&#xff1f; 为什么要进…

循环神经网络和自然语言处理一

目录 一.分词 1.分词工具 2.分词的方法 3.N-gram表示方法 二.向量化 1.one-hot编码 2.word embedding 3.word embedding API 4.数据形状改变 既然是自然语言&#xff0c;那么就有字&#xff0c;词&#xff0c;句了 一.分词 1.分词工具 tokenization&#xff0c;jie…

Outlook Pst文件大小最大多大?如何分开缩减?

簡介 預設情況下&#xff0c;personal Folders (.pst) 和離線 Outlook Data File (.ost) 檔案在 Microsoft Outlook 2010 和 Outlook 2013 中為 Unicode 格式。 .pst 和 .ost 檔案的整體大小有 50 GB 的預先設定限制。 此限制大於 2007 和 Outlook 2003 Outlook Unicode .pst …

零基础5分钟上手亚马逊云科技AWS核心云开发/云架构知识 - 成本分析篇

简介&#xff1a; 欢迎来到小李哥全新亚马逊云科技AWS云计算知识学习系列&#xff0c;适用于任何无云计算或者亚马逊云科技技术背景的开发者&#xff0c;让大家零基础5分钟通过这篇文章就能完全学会亚马逊云科技一个经典的服务开发架构方案。 我将每天介绍一个基于亚马逊云科…

数据结构 - 相邻节点迭代器

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、相邻节…

nuxt3实战:完整的 nuxt3 + vue3 项目创建与useFetch请求封装

一. 安装 pnpm dlx nuxilatest init <project-name>// ornpx nuxilatest init <project-name>如遇到报错 手动安装&#xff1a; 浏览器访问报错https请求地址&#xff1a; 点击tar(项目初始文件的下载地址)对应地址,下载starter-3.tar.gz 包到本地 本地创建项…

【Android】使用网络技术——WebView的用法、http协议、OKHttp、解析XML、JSON格式数据笔记整理

WebView的用法 新建一个WebView项目 修改activity_main中的代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:id"id/main"and…

STM32F1之SysTick系统定时器详细解析

目录 1. 简介 2. SysTick功能框图 3. SysTick寄存器 3.1 SysTick控制及状态寄存器 3.2 SysTick重装载数值寄存器 3.3 SysTick当前数值寄存器 3.4 SysTick校准数值寄存器 4. SysTick定时时间计算 5. SysTick寄存器结构体 6. 写一个us级延时函数 7. 写一个…

240806-RHEL 无法通过 ssh username@ip 远程连接,报错:Connection closed by ip port 22

A. 原因排查 遇到这个错误通常意味着 SSH 服务可能在目标主机上没有正常运行&#xff0c;或有防火墙/网络配置问题。以下是一些排查步骤&#xff1a; 检查 SSH 服务状态&#xff1a; 确认 SSH 服务是否正在目标主机上运行。 sudo systemctl status sshd重启 SSH 服务&#xff…

探索 Python 异步通信的奥秘:WebSockets 库的神奇之旅

文章目录 探索 Python 异步通信的奥秘&#xff1a;WebSockets 库的神奇之旅背景&#xff1a;为何选择 WebSockets&#xff1f;什么是 websockets 库&#xff1f;安装 websockets 库5个简单的库函数使用方法场景应用示例常见问题与解决方案总结 探索 Python 异步通信的奥秘&…

用Manim实现三维坐标系的绘制

1.ThreeDAxes 函数 ThreeDAxes是 Manim 中用于创建三维坐标系的类。在manim中常用的三位坐标绘制函数是&#xff1a; class ThreeDAxes(x_range(-6, 6, 1), y_range(-5, 5, 1), z_range(-4, 4, 1), x_length10.5, y_length10.5, z_length6.5, z_axis_configNone, z_normala…

数据仓库怎么建设?一文详解数仓的建设过程!

随着信息技术的飞速发展&#xff0c;企业不仅需要存储和管理海量数据&#xff0c;更迫切需要从这些数据中提取有价值的信息&#xff0c;以支持复杂的决策制定过程。数据仓库不仅是存储数据的场所&#xff0c;更是支持复杂查询、报告和数据分析的强有力工具&#xff0c;其建设已…