java基础(2) 面向对象编程-java核心类

面向对象

面向对象对应的就是面向过程,
面向过程就是一步一步去操作,你需要知道每一步的步骤。
面向对象的编程以对象为核心,通过定义类描述实体及其行为,并且支持继承、封装和多态等特性

面向对象基础

面向对象编程,是一种通过对象的方式,把现实世界映射到计算机模型的一种编程方法。
现实世界中,我们定义了“人”这种抽象概念,而具体的人则是“小明”、“小红”、“小军”等一个个具体的人。所以,“人”可以定义为一个类(class),而具体的人则是实例(instance):
在这里插入图片描述

class Test {
    private int field1;
    public String field2;
    // 构造函数
 	public Test(String field2, int field1) {
        this.field1 = field1;
        this.field2 = field2;
    }

    public int getField1(){
        return this.field1;
    }

    public  void setField1(int val){
        if(val < 0 || val > 100){
            // 抛出错误
            throw new IllegalArgumentException("invalid age value");
        }
        // 赋值
        this.field1 = val;
    }
};

public class Main {
	public static void main(String[] args){
		Test t = new Test();
        t.setField1(2);
        System.out.println(t.getField1());
        System.out.println(t.field2);
	}
}

写法同js类型,但是需要指定Test类型。一般字段使用private修饰符修饰,表示私有属性,外部无法访问,但是可以通过设置公共的方法去获取和设置值。
java类的构造函数,是public 类名(){},跟js的constructor(){}还是有点区别的。并且java可以写多个构造方法。除此之外,构造方法之间还能相互调用。

class Person {
    private String name;
    private int age;

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

    public Person(String name) {
        this(name, 18); // 调用另一个构造方法Person(String, int)
    }

    public Person() {
        this("Unnamed"); // 调用另一个构造方法Person(String)
    }
}
方法重载

如果有一系列方法,它们的功能都是类似的,只有参数有所不同,那么,可以把这一组方法名做成同名方法。
方法重载的目的是,功能类似的方法使用同一名字,更容易记住,因此,调用起来更简单。

 public  void setField1(int val){
        if(val < 0 || val > 100){
            // 抛出错误
            throw new IllegalArgumentException("invalid age value");
        }
        // 赋值
        this.field1 = val;
    }
    public  void setField1(int val, boolean isTrue){
        if(val < 0 || val > 100){
            // 抛出错误
            throw new IllegalArgumentException("invalid age value");
        }
        // 赋值
        this.field1 = val;
    }
   

比如String.indexOf()方法,就提供了多种调用方法。

举个例子,String类提供了多个重载方法indexOf(),可以查找子串:
int indexOf(int ch):根据字符的Unicode码查找;
int indexOf(String str):根据字符串查找;
int indexOf(int ch, int fromIndex):根据字符查找,但指定起始位置;
int indexOf(String str, int fromIndex)根据字符串查找,但指定起始位置。
继承

所有的类都默认继承与object,只有object例外,他没有父类。
java的继承同js差不多,只有一点区别,这里不多详述。

多态

子类可以重写父类的方法。这里需要注意,只有方法名,参数,返回值相同,才算是重写。加上@Overide装饰器可以方便编译器检查报错。

class Person {
    public void run() {
        System.out.println("Person.run");
    }
}
class Student extends Person {
    @Override
    public void run() {
        System.out.println("Student.run");
    }
}

多态是指,针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法;
没运行之前不知道运行的是父类的方法还是子类的方法。

如果父类不想子类继承某个方法,可以用final修饰方法。

class Person {
    protected String name;
    public final String hello() {
        return "Hello, " + name;
    }
}

用final修饰的类不允许被继承
用final修饰的属性,不允许被重新赋值

抽象类

如果父类的方法本身不需要实现任何功能,仅仅是为了定义方法签名,目的是让子类去覆写它,那么,可以把父类的方法声明为抽象方法:

 abstract class Person {
    public abstract void run();
}

包含抽象方法的类不允许被实例化。抽象类强迫子类必须实现他的抽象方法。
用法跟ts类似,这里不多详述

面向抽象编程的本质就是:
  • 上层代码只定义规范(例如:abstract class Person);
  • 不需要子类就可以实现业务逻辑(正常编译);
  • 具体的业务逻辑由不同的子类实现,调用者并不关心。
接口

没有字段的,且全部方位都是抽象方法的抽象类,就可以改写为接口。

abstract class Person {
    public abstract void run();
    public abstract String getName();
}
//改写为
interface Person {
    void run();
    String getName();
}

接口定义的所有方法默认都是public abstract的
而当一个具体的类想去实现一个接口的时候,就需要使用implements,而非extends。
一个类只能继承于一个类,但是一个类可以implements多个接口。

在这里插入图片描述
接口之间也可以通过extends去继承。
接口还可以定义一个非抽象方法default,这个不强求类去实现,目的是为了:
当我们需要给接口新增一个方法时,会涉及到修改全部子类。如果新增的是default方法,那么子类就不必全部修改,只需要在需要覆写的地方去覆写新增方法。

静态字段和静态方法

实例字段在每个实例中都有自己的一个独立“空间”,但是静态字段只有一个共享“空间”,所有实例都会共享该字段。举个例子:

class Person {
    public String name;
    public int age;
    // 定义静态字段number:
    public static int number;
}

对于静态字段,无论修改哪个实例的静态字段,效果都是一样的:所有实例的静态字段都被修改了,原因是静态字段并不属于实例;
在这里插入图片描述
可以把静态字段立即为类自己的属性,一般通过类.字段去获取,而不是通过实例.字段去获取。

同理,静态方法也一致,属于类,可以直接通过类.方法名去调用,但是内部无法访问this。
静态方法经常用于工具类。例如:
Arrays.sort()
Math.random()

在Java中,我们使用package来解决名字冲突。
Java定义了一种名字空间,称之为包:package。一个类总是属于某个包,类名(比如Person)只是一个简写,真正的完整类名是包名.类名。
类似于ts的namespace,防止命名冲突。
JDK的Arrays类存放在包java.util下面,因此,完整类名是java.util.Arrays。
包的命名跟文件存放位置也有关。
在这里插入图片描述

导入其他包

  • 直接写完整的包名: lin.TestClass
  • 先在当前包import lin.TestClass ,就可以直接用了new TestClass
  • 也可以直接import lin.*,他会将lin包的class引入。
  • 默认引入java.lang的包,比如String, 这些。
作用域

比如public、protected、private,这些修饰符,用来限定作用域的范围。
publci的类,可以被其他包访问。public的属性和方法,也可以被其他类访问。
非publci的类,外部无法访问,就跟js没有export一样
private定义的方法和属性,无法在类外被访问。
由于Java支持嵌套类,如果一个类内部还定义了嵌套类,那么,嵌套类拥有访问private的权限:

public class Main {
    public static void main(String[] args) {
        Inner i = new Inner();
        i.hi();
    }

    // private方法:
    private static void hello() {
        System.out.println("private hello!");
    }

    // 静态内部类:
    static class Inner {
        public void hi() {
            Main.hello();
        }
    }
}

private定义的字段和方法,其继承类中无法使用,procted修饰的方法和字段,可以在子类中使用,但同样不可以被实例调用。

package权限(包作用域)
最后,包作用域是指一个类允许访问同一个package的没有private修饰的class,以及没有protected、private修饰的字段和方法。
final

  • 用final修饰class可以阻止被继承:
  • 用final修饰method可以阻止被子类覆写
  • 用final修饰字段可以阻止被重新赋值
  • 用final修饰局部变量可以阻止被重新赋值
内部类

在这里插入图片描述

也是嵌套类。

classpath和jar

classpath是JVM用到的一个环境变量,它用来指示JVM如何搜索class
现在我们假设classpath是.;C:\work\project1\bin;C:\shared,当JVM在加载abc.xyz.Hello这个类时,会依次查找:

  • <当前目录>\abc\xyz\Hello.class
  • C:\work\project1\bin\abc\xyz\Hello.class
  • C:\shared\abc\xyz\Hello.class

在系统环境变量中设置classpath环境变量,不推荐;
在启动JVM时设置classpath变量,推荐。
启动jvm的时候🌽定义
java -classpath .;C:\work\project1\bin;C:\shared abc.xyz.Hello

jar包

如果有很多.class文件,散落在各层目录中,肯定不便于管理。如果能把目录打一个包,变成一个文件,就方便多了。

jar包就是用来干这个事的,它可以把package组织的目录层级,以及各个目录下的所有文件(包括.class文件和其他文件)都打成一个jar文件,这样一来,无论是备份,还是发给客户,就简单多了。

jar包相当于目录,可以包含很多.class文件,方便下载和使用;

MANIFEST.MF文件可以提供jar包的信息,如Main-Class,这样可以直接运行jar包。

java核心类

字符串

实际上字符串在String内部是通过一个char[]数组表示的,因此,按下面的写法也是可以的:

String s2 = new String(new char[] {'H', 'e', 'l', 'l', 'o', '!'});

Java字符串的一个重要特点就是字符串不可变。这种不可变性是通过内部的private final char[]字段,以及没有任何修改char[]的方法实现的。
不可变不是说变量s2不可变,s2可以重新赋值一个新的String对象,只不过原有的String对象不会改变。

字符串比较

java拥有一个字符串常量池,如果多个字符串具有相同的值,那么他们将共享存储在常量池中的同一个实例,也就是说
String s = "hello",这个hello,实际上是存放在常量池中,s存放的值是hello的地址,类似于js的对象,只不过js的字符串是基础类型而不是引用类型。
当我们想要比较两个字符串是否相同时,要特别注意,我们实际上是想比较字符串的内容是否相同。必须使用equals()方法而不能用==
因为==实际上比较的是内存地址,

 		String s1 = "hello";
        String s2 = "HELLO".toLowerCase();
        System.out.println(s1 == s2);
        System.out.println(s1.equals(s2));

==返回false,只有equals才返回true。

其他字符串方法同js类似

"Hello".indexOf("l"); // 2
"Hello".lastIndexOf("l"); // 3
"Hello".startsWith("He"); // true
"Hello".endsWith("lo"); // true
"Hello".substring(2); // "llo"
"Hello".substring(2, 4); "ll"
"  \tHello\r\n ".trim(); // "Hello" 返回的Hello是新的String对象

"".isEmpty(); // true,因为字符串长度为0
"  ".isEmpty(); // false,因为字符串长度不为0
"  \n".isBlank(); // true,因为只包含空白字符
" Hello ".isBlank(); // false,因为包含非空白字符

String[] arr = {"A", "B", "C"};
String s = String.join("***", arr); // "A***B***C"


//字符串占位 
String s = "Hi %s, your score is %d!";
System.out.println(s.formatted("Alice", 80));
System.out.println(String.format("Hi %s, your score is %.2f!", "Bob", 59.5));

字符串转换

要把任意基本类型或引用类型转换为字符串,可以使用静态方法valueOf()。这是一个重载方法,编译器会根据参数自动选择合适的方法。

String.valueOf(123); // "123"
String.valueOf(45.67); // "45.67"
String.valueOf(true); // "true"
String.valueOf(new Object()); // 类似java.lang.Object@636be97c

//int
int n1 = Integer.parseInt("123"); // 123
int n2 = Integer.parseInt("ff", 16); // 按十六进制转换,255

// boolean
boolean b1 = Boolean.parseBoolean("true"); // true
boolean b2 = Boolean.parseBoolean("FALSE"); // false

// char 和 String 互转
char[] cs = "Hello".toCharArray(); // String -> char[]
String s = new String(cs); // char[] -> String


byte[] b1 = "Hello".getBytes(); // 按系统默认编码转换,不推荐
byte[] b2 = "Hello".getBytes("UTF-8"); // 按UTF-8编码转换
byte[] b2 = "Hello".getBytes("GBK"); // 按GBK编码转换
byte[] b3 = "Hello".getBytes(StandardCharsets.UTF_8); // 按UTF-8编码转换

byte[] b = ...
String s1 = new String(b, "GBK"); // 按GBK转换
String s2 = new String(b, StandardCharsets.UTF_8); // 按UTF-8转换
小结
  • Java字符串String是不可变对象;
  • 字符串操作不改变原字符串内容,而是返回新字符串;
  • 常用的字符串操作:提取子串、查找、替换、大小写转换等;
  • Java使用Unicode编码表示String和char;
  • 转换编码就是将String和byte[]转换,需要指定编码;
  • 转换为byte[]时,始终优先考虑UTF-8编码。
StringBuilder

Java编译器对String做了特殊处理,使得我们可以直接用+拼接字符串
但是

String s = "";
for (int i = 0; i < 1000; i++) {
    s = s + "," + i;
}

上面循环代码,每次循环都会创建新的String对象,而老的String对象则被丢弃,造成内存浪费,所以java提供StringBuilder来高校拼接String;
Java标准库提供了StringBuilder,它是一个可变对象,可以预分配缓冲区,这样,往StringBuilder中新增字符时,不会创建新的临时对象:

StringBuilder sb = new StringBuilder(1024);
for (int i = 0; i < 1000; i++) {
    sb.append(',').append(i);
}
String s = sb.toString();

注意:对于普通的字符串+操作,并不需要我们将其改写为StringBuilder,因为Java编译器在编译时就自动把多个连续的+操作编码为StringConcatFactory的操作。在运行期,StringConcatFactory会自动把字符串连接操作优化为数组复制或者StringBuilder操作。

小结

  • StringBuilder是可变对象,用来高效拼接字符串;
  • StringBuilder可以支持链式操作,实现链式操作的关键是返回实例本身;
StringJoiner

类似用分隔符拼接数组的需求很常见,所以Java标准库还提供了一个StringJoiner来干这个事:

public class Main {
    public static void main(String[] args) {
        String[] names = {"Bob", "Alice", "Grace"};
        var sj = new StringJoiner(", ", "Hello ", "!");
        for (String name : names) {
            sj.add(name);
        }
        System.out.println(sj.toString());
    }
}

第一个参数指定拼接的字符串,第二个参数指定开头,第三个参数指定结尾。
String还提供了一个静态方法join(),这个方法在内部使用了StringJoiner来拼接字符串,在不需要指定“开头”和“结尾”的时候

String[] names = {"Bob", "Alice", "Grace"};
var s = String.join(", ", names);
包装类型

在这里插入图片描述
Integer类实现,

public class Integer {
    private int value;

    public Integer(int value) {
        this.value = value;
    }

    public int intValue() {
        return this.value;
    }
}

在这里插入图片描述

有点像js中,string对应的String, number对应的Numer,
int 和Integer可以互相转换

int i = 100;
Integer n = Integer.valueOf(i);
int x = n.intValue();

Integer n = 100; // 编译器自动使用Integer.valueOf(int)
int x = n; // 编译器自动使用Integer.intValue()

所有的包装类都是不变类,

public final class Integer {
    private final int value;
}

init在初始化赋值之后,将不能再修改;
对两个Integer实例进行比较要特别注意:绝对不能用==比较,因为Integer是引用类型,必须使用equals()比较

public class Main {
    public static void main(String[] args) {
        Integer x = 127;
        Integer y = 127;
        Integer m = 99999;
        Integer n = 99999;
        System.out.println("x == y: " + (x==y)); // true
        System.out.println("m == n: " + (m==n)); // false
        System.out.println("x.equals(y): " + x.equals(y)); // true
        System.out.println("m.equals(n): " + m.equals(n)); // true
    }
}

值较小的Integer比较是相等的,这是因为,在Integer内部,为了优化性能,对于较小的,Integer.initValue总是返回同一个实例,这也导致==为true。

Integer x = 127
//等同于
Integer x = Integer.valueOf(127)

Integer.valueOf()就是静态工厂方法,它尽可能地返回缓存的实例以节省内存。
创建新对象时,优先选用静态工厂方法而不是new操作符。

进制转换

Integer本身还提供了很多方法,就跟js的Number.xxx一样,

  • parseInt 将其他类型转为Integer类型
int x1 = Integer.parseInt("100"); // 100
int x2 = Integer.parseInt("100", 16); // 256,因为按16进制解析

System.out.println(Integer.toString(100)); // "100",表示为10进制
System.out.println(Integer.toString(100, 36)); // "2s",表示为36进制
System.out.println(Integer.toHexString(100)); // "64",表示为16进制
System.out.println(Integer.toOctalString(100)); // "144",表示为8进制
System.out.println(Integer.toBinaryString(100)); // "1100100",表示为2进制

Java的包装类型还定义了一些有用的静态变量

// boolean只有两个值true/false,其包装类型只需要引用Boolean提供的静态字段:
Boolean t = Boolean.TRUE;
Boolean f = Boolean.FALSE;
// int可表示的最大/最小值:
int max = Integer.MAX_VALUE; // 2147483647 类似于js的x`
int min = Integer.MIN_VALUE; // -2147483648
// long类型占用的bit和byte数量:
int sizeOfLong = Long.SIZE; // 64 (bits)
int bytesOfLong = Long.BYTES; // 8 (bytes)

所有的整数和浮点数的包装类型都继承Number,因此,可以非常方便地直接通过包装类型获取各种基本类型:

// 向上转型为Number:
Number num = new Integer(999);
// 获取byte, int, long, float, double:
byte b = num.byteValue();
int n = num.intValue();
long ln = num.longValue();
float f = num.floatValue();
double d = num.doubleValue();
JavaBean

符合以下这种

// 读方法:
public Type getXyz()
// 写方法:
public void setXyz(Type value)

读写方法名分别以get和set开头,并且后接大写字母开头的字段名Xyz,因此两个读写方法名分别是getXyz()和setXyz()。
类似于js的defineProperty的get set方法。

JavaBean是一种符合命名规范的class,它通过getter和setter来定义属性;
属性是一种通用的叫法,并非Java语法规定;
可以利用IDE快速生成getter和setter;
使用Introspector.getBeanInfo()可以获取属性列表。

枚举类

在Java中,我们可以通过static final来定义常量

public class Weekday {
    public static final int SUN = 0;
    public static final int MON = 1;
    public static final int TUE = 2;
    public static final int WED = 3;
    public static final int THU = 4;
    public static final int FRI = 5;
    public static final int SAT = 6;
}

enum
为了让编译器能自动检查某个值在枚举的集合内,并且,不同用途的枚举需要不同的类型来标记,不能混用,我们可以使用enum来定义枚举类:

public class Main {
    public static void main(String[] args) {
        Weekday day = Weekday.SUN;
        if (day == Weekday.SAT || day == Weekday.SUN) {
            System.out.println("Work at home!");
        } else {
            System.out.println("Work at office!");
        }
    }
}

enum Weekday {
    SUN, MON, TUE, WED, THU, FRI, SAT;
}

有点类型于ts的enum,

  • 不同类型的枚举,不能相互赋值。
  • 不同类型的值,不可以直接==
 Test1 tt = Test1.TEST_1;
tt = HAHA.HAHA_1;
int test = 1;
test == Test1.TEST_1;


enum Test1 { TEST_1, TEST_2 };
enum HAHA {HAHA_1, HAHA_2};

enum实际上创建的也是一个class

  • 定义的enum类型总是继承自java.lang.Enum,且无法被继承;
  • 只能定义出enum的实例,而无法通过new操作符创建enum的实例;
  • 定义的每个实例都是引用类型的唯一实例;
  • 可以将enum类型用于switch语句。
public enum Color {
    RED, GREEN, BLUE;
}
//实际上

public final class Color extends Enum { // 继承自Enum,标记为final class
    // 每个实例均为全局唯一:
    public static final Color RED = new Color();
    public static final Color GREEN = new Color();
    public static final Color BLUE = new Color();
    // private构造方法,确保外部无法调用new操作符:
    private Color() {}
}

每个实例都是全局唯一
编译后的enum类和普通class并没有任何区别。但是我们自己无法按定义普通class那样来定义enum,必须使用enum关键字,这是Java语法规定的。

因为enum是一个class,每个枚举的值都是class实例,因此,这些实例有一些方法:name()

String s = Weekday.SUN.name(); // "SUN"
int n = Weekday.MON.ordinal(); // 1 返回定义的常量的顺序,从0开始计数

因为enum实际上定义的也是类,所以可以根据构造函数,添加每个实例对应的属性。比如

enum Weekday {
    MON(1), TUE(2), WED(3), THU(4), FRI(5), SAT(6), SUN(0);

    public final int dayValue;

    private Weekday(int dayValue) {
        this.dayValue = dayValue;
    }
}

 public static void main(String[] args) {
        Weekday day = Weekday.SUN;
        if (day.dayValue == 6 || day.dayValue == 0) {
            System.out.println("Work at home!");
        } else {
            System.out.println("Work at office!");
        }
    }

MON(1)相当于执行new操作,将1传入作为dataValue的值,这样就可以通过.dataValue去获取值。
再比如

enum Weekday {
    MON(1, "星期一"), TUE(2, "星期二"), WED(3, "星期三"), THU(4, "星期四"), FRI(5, "星期五"), SAT(6, "星期六"), SUN(0, "星期日");

    public final int dayValue;
    private final String chinese;

    private Weekday(int dayValue, String chinese) {
        this.dayValue = dayValue;
        this.chinese = chinese;
    }

    @Override
    public String toString() {
        return this.chinese;
    }
}

还可以多用其他属性,然后重新toString方法。name属于final,无法被重写。
小结

  • Java使用enum定义枚举类型,它被编译器编译为final class Xxx extends Enum { … };
  • 通过name()获取常量定义的字符串,注意不要使用toString();
  • 通过ordinal()返回常量定义的顺序(无实质意义);
  • 可以为enum编写构造方法、字段和方法
  • enum的构造方法要声明为private,字段强烈建议声明为final;
  • enum适合用在switch语句中。
BigInteger BigDecimal

整数最大是long类型,超过了的话,java.math.BigInteger就是用来表示任意大小的整数。BigInteger内部用一个int[]数组来模拟一个非常大的整数:

BigInteger bi = new BigInteger("1234567890");
System.out.println(bi.pow(5)); // 2867971860299718107233761438093672048294900000

和BigInteger类似,BigDecimal可以表示一个任意大小且精度完全准确的浮点数。
实际上一个BigDecimal是通过一个BigInteger和一个scale来表示的,即BigInteger表示一个完整的整数,而scale表示小数位数

public class BigDecimal extends Number implements Comparable<BigDecimal> {
    private final BigInteger intVal;
    private final int scale;
}
常用工具类

Math
顾名思义,Math类就是用来进行数学计算的,它提供了大量的静态方法来便于我们实现数学计算:

Math.abs(-13) //13 绝对值
Math.max(13,9) //13 最大
Math.min() //最小
Math.pow(2, 10); // 2的10次方=1024
double pi = Math.PI; // 3.14159...
double e = Math.E; // 2.7182818...
Math.sin(Math.PI / 6); // sin(π/6) = 0.5
Math.random(); // 0.53907... 每次都不一样

Java标准库还提供了一个StrictMath,它提供了和Math几乎一模一样的方法。这两个类的区别在于,由于浮点数计算存在误差,不同的平台(例如x86和ARM)计算的结果可能不一致(指误差不同),因此,StrictMath保证所有平台计算结果都是完全相同的,而Math会尽量针对平台优化计算速度,所以,绝大多数情况下,使用Math就足够了。
·
Random
生成伪随机数

Random r = new Random();
r.nextInt(); // 2071575453,每次都不一样
r.nextInt(10); // 5,生成一个[0,10)之间的int
r.nextLong(); // 8811649292570369305,每次都不一样
r.nextFloat(); // 0.54335...生成一个[0,1)之间的float
r.nextDouble(); // 0.3716...生成一个[0,1)之间的double

SecureRandom
有伪随机数,就有真随机数。实际上真正的真随机数只能通过量子力学原理来获取,而我们想要的是一个不可预测的安全的随机数,SecureRandom就是用来创建安全的随机数的:

SecureRandom sr = new SecureRandom();
System.out.println(sr.nextInt(100));

SecureRandom的安全性是通过操作系统提供的安全的随机种子来生成随机数。这个种子是通过CPU的热噪声、读写磁盘的字节、网络流量等各种随机事件产生的“熵”。

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

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

相关文章

吉他学习:识谱,认识节奏,视唱节奏,节拍器的使用

第九课 识谱https://m.lizhiweike.com/lecture2/29362692 第十课 基础乐理(二)——节奏篇https://mp.csdn.net/mp_blog/creation/editor?spm=1011.2124.3001.6192

CPU和GPU有什么区别,玩游戏哪个更重要?

大家好&#xff01;今天我们要聊的话题是CPU和GPU&#xff0c;它们在电脑中扮演着重要的角色&#xff0c;虽然看起来只是两个简单的缩写&#xff0c;但它们的功能和影响是截然不同的&#xff01; 那么&#xff0c;究竟CPU和GPU有什么区别呢&#xff1f;在玩游戏时&#xff0c;…

OCP使用web console创建和构建应用

文章目录 环境登录创建project赋予查看权限部署第一个image检查pod扩展应用 部署一个Python应用连接数据库创建secret加载数据并显示国家公园地图 清理参考 环境 RHEL 9.3Red Hat OpenShift Local 2.32 登录 在 crc start 启动crc时&#xff0c;可以看到&#xff1a; .....…

寒假作业2024.2.6

1.现有无序序列数组为23,24,12,5,33,5347&#xff0c;请使用以下排序实现编程 函数1:请使用冒泡排序实现升序排序 函数2:请使用简单选择排序实现升序排序 函数3:请使用直接插入排序实现升序排序 函数4:请使用插入排序实现升序排序 #include <stdio.h> #include <stdl…

机器学习11-前馈神经网络识别手写数字1.0

在这个示例中&#xff0c;使用的神经网络是一个简单的全连接前馈神经网络&#xff0c;也称为多层感知器&#xff08;Multilayer Perceptron&#xff0c;MLP&#xff09;。这个神经网络由几个关键组件构成&#xff1a; 1. 输入层 输入层接收输入数据&#xff0c;这里是一个 28x…

空气质量预测 | Matlab实现基于SVR支持向量机回归的空气质量预测模型

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 政府机构使用空气质量指数 (AQI) 向公众传达当前空气污染程度或预测空气污染程度。 随着 AQI 的上升,公共卫生风险也会增加。 不同国家有自己的空气质量指数,对应不同国家的空气质量标准。 基于支持向量机(Su…

真正免费的文件恢复软件easyrecovery2024中文版

easyrecovery数据恢复软件是一款广受好评的数据恢复工具&#xff0c;它能够有效地帮助用户恢复各种类型的文件。无论是照片、视频、音乐还是文档&#xff0c;都能轻松地找回这些重要文件。操作安全、用户可自主操作的数据恢复方案&#xff0c;它支持从各种各样的存储介质恢复删…

备战蓝桥杯---动态规划之背包问题引入

先看一个背包问题的简单版&#xff1a; 如果我们暴力枚举可能会超时。 但我们想一想&#xff0c;我们其实不关心怎么放&#xff0c;我们关心的是放后剩下的体积。 用可行性描述即可。 于是我们令f[i][j]表示前i个物品能否放满体积为j的背包。 f[i][j]f[i-1][j]||f[i-1][j-v…

Mysql为什么使用B+Tree作为索引结构

B树和B树 一般来说&#xff0c;数据库的存储引擎都是采用B树或者B树来实现索引的存储。首先来看B树&#xff0c;如图所示&#xff1a; B树是一种多路平衡树&#xff0c;用这种存储结构来存储大量数据&#xff0c;它的整个高度会相比二叉树来说&#xff0c;会矮很多。 而对于数…

【Spring源码解读!底层原理高级进阶】【上】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;底层原理高级进阶》 &#x1f680…

C#上位机与三菱PLC的通信05--MC协议之QnA-3E报文解析

1、MC协议回顾 MC是公开协议 &#xff0c;所有报文格式都是有标准 &#xff0c;MC协议可以在串口通信&#xff0c;也可以在以太网通信 串口&#xff1a;1C、2C、3C、4C 网口&#xff1a;4E、3E、1E A-1E是三菱PLC通信协议中最早的一种&#xff0c;它是一种基于二进制通信协…

windows10安装配置nvm以达到切换nodejs的目的

前言 各种各样的项目&#xff0c;各种node环境&#xff0c;还有node_modules这个庞然大物。。想想都觉得恐怖。 所以现在有了&#xff1a;nvm-切换node环境&#xff0c;pnpm–解决重复下载同样类库的问题。 下面将就如何在win10下配置进行说明 nvm下载配置 nvm的github下载地…

Flink从入门到实践(三):数据实时采集 - Flink MySQL CDC

文章目录 系列文章索引一、概述1、版本匹配2、导包 二、编码实现1、基本使用2、更多配置3、自定义序列化器4、Flink SQL方式 三、踩坑1、The MySQL server has a timezone offset (0 seconds ahead of UTC) which does not match the configured timezone Asia/Shanghai. 参考资…

kmeans聚类选择最优K值python实现

Kmeans算法中K值的确定是很重要的。 下面利用python中sklearn模块进行数据聚类的K值选择 数据集自制数据集&#xff0c;格式如下&#xff1a; 维度为3。 ①手肘法 手肘法的核心指标是SSE(sum of the squared errors&#xff0c;误差平方和)&#xff0c; 其中&#xff0c;Ci是第…

微调LLM或使用RAG,开发RAG管道的12个痛点

论文地址&#xff1a;archive.is/bNbZo Pain Point 1: Missing Content 内容缺失 Pain Point 2: Missed the Top Ranked Documents 错过排名靠前的文档 Pain Point 3: Not in Context — Consolidation Strategy Limitations 不在上下文中 — 整合战略的局限性 Pain Point …

免费生成ios证书的方法(无需mac电脑)

使用hbuilderx的uniapp框架开发移动端程序很方便&#xff0c;可以很方便地开发出移动端的小程序和app。但是打包ios版本的app的时候却很麻烦&#xff0c;官方提供的教程需要使用mac电脑来生成证书&#xff0c;但是mac电脑却不便宜&#xff0c;一般的型号都差不多上万。 因此&a…

【Java面试】数据类型常见面试题

什么是包装类型 将基本类型包装进了对象中得到的类型 基本类型和包装类型有什么区别 用途不同&#xff1a;基本类型一般用于局部变量&#xff0c;包装类型用于其他地方存储方式不同&#xff1a;用于局部变量的基本类型存在虚拟机栈中的局部变量表中&#xff0c;用于成员变量…

火星符号运算 - 华为OD统一考试

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 已知火星人使用的运算符号为 #和$ 其与地球人的等价公式如下 x#y2*x3*y4 x$y3*xy2x y是无符号整数。地球人公式按照c语言规则进行计算。火星人公式中&#xff0…

基于鲲鹏服务器的LNMP配置

基于鲲鹏服务器的LNMP配置 系统 Centos8 # cat /etc/redhat-release CentOS Linux release 8.0.1905 (Core) 卸载已经存在的旧版本的安装包 # rpm -qa | grep php #查看已经安装的PHP旧版本# rpm -qa | grep php | xargs rpm -e #卸载已经安装的旧版&#xff0c;如果提示有…

113.路径总和 II

给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum 22 输出&a…