Java

Java

Hello world!

image-20240926164131545

psvm解释语句,main方法,main(参数),以上无参数,sout输出

注:

  • 注意大小写
  • 文件名和类名需要保持一致
  • 命名规则,首字母小写 驼峰式命名

标识符

  • 能字母,$,_,开头
  • 不能以关键字作为变量名或方法名
  • 注意大小写(大写的跟小写的不是同一个变量)
  • 不能以特殊符号,数字来命名
  • 下划线之后可以存在数字

image-20240926173231335

占位符

%表示占位符,因此,连续两个%%表示一个%字符本身

占位符 说明
%d 格式化输出整数
%x 格式化输出十六进制整数
%f 格式化输出浮点数
%e 格式化输出科学计数法表示的浮点数
%s 格式化字符串

数据类型

基本类型

image-20240926174647432

image-20240926174356424

拓展

整数

image-20240926175445238

浮点数

image-20240926180159672

float接近但不等于,大约 (少用浮点数进行比较 有误差)

字符

强制转换成数字(字符的本质是数字)

image-20240926180743772

编码

image-20240926181117678

转义字符

\t	制表符
\n	换行

ps:

if (flag==true){}
和
if (flag){}
是一样的,只是写法不同

类型转换

image-20240926191150268

强制转换 :(类型)变量名 高到底

自动转换: ... 低到高

  • 不能对布尔值进行转换
  • 存在内存溢出或精度问题

image-20240926191959631

image-20240926192143551

image-20240926192536368

变量

变量作用域

赋值

变量的一个重要特征是可以重新赋值

第一次赋值时定义过了变量类型,第二次赋值时则不需要重新赋值

image-20241009200336737

将一个变量的值重新赋值另一个变量

image-20241009201721838

类变量

从属于类,随着类一起存在一起消失

image-20240926210750001

实例变量

从属于对象,如果未设置初始化,输出类型的默认值

image-20240926210451017

局部变量

必须声名和初始化值

定义在某个方法内,当程序执行完该方法的时候 无法调用该变量

常量

final 常量名 常量值

变量命名

image-20240926212241648

运算符

image-20240926212513092

自增 自减

image-20240926215532055

逻辑运算符

image-20240926220241599

b是假 上来就结束运行 称为短路运算

image-20240926220445301

如果后面的运行 结果为6

位运算

image-20240926221559373

当出现字符串时,后面的数字将会被转化成字符串类型显示出来 所以输出是1020

image-20240927082629966

三元运算符

b ? x : y

image-20240927083108429

包机制

包 其实就是文件夹

利用公司域名倒置作包名 eg:com.baidu.www

image-20240927085811946

image-20240927101503378

导入包

image-20240927102245781

Doc

参数信息

@author 作者名
@version 版本号
@since 指明需要最早使用的的jdk版本
@return 返回值情况
@throws 异常抛出情况

生成Doc文档

命令行:javadoc 参数 java文件

javadoc -encoding UTF-8 -charset UTF-8 Doc.java

image-20240927091714852

image-20240927091749665

IDEA生成doc文档

image-20240927094021232

生成doc

image-20240927095514764

生成了

image-20240927095658960

image-20240927095630030

控制流程

输入

``System.in代表标准输入流

Scanner对象

通过Scanner类来获取用户的输入,通过Scanner类的next()nextLine()方法获取输入的字符串,用hasNext()hasNextLine()判断是否还有输入的数据

image-20240927112231974

next

image-20240927112442836

nextLine

image-20240927112520634

简洁版

image-20240927112913289

判断

image-20240927164455871

image-20240927164620441

求和 平均数

image-20240927170226256

image-20240927170545641

输出

``System.out代表标准输出流

顺序结构

选择结构

image-20240927172707194

image-20240927172720680

多选择结构

if,else,else if

image-20240927215215413

switch case语句

case穿透

当没有break语句时,会将下面的语句全部输出,而不是可选模式

image-20240927220453747

反编译

image-20240927221202862

文件夹 拷贝文件

image-20240927221411854

反编译文件

image-20240927221444174

中文时通过哈希值来比较

image-20240927221602271

判断引用类型相等

  • 判断引用类型的变量是否相等用 ==

  • 判断引用类型的变量内容是否相等用 equals()方法

循环结构

while循环

如果不满足条件,则不能进入循环

先判断后执行

image-20240928091137451

image-20240928091531427

do...while

即使不满足while循环条件,至少也会执行一次循环

先执行后判断

image-20240928092515326

while和do..while循环的区别

image-20240928093022859

for循环

for(初始化;布尔表达式;更新){
	//代码
}

image-20240928093710131

计算1-100之间的奇数和,偶数和

image-20240928095128953

计算1-1000之间的能被5整除的数,并且3个数一换行

image-20240928100525715

注:

println输出完 会换行

print输出完 不会换行

九九乘法表

image-20240928102219525

增强for循环

image-20240928105301569

语句更简便

breakcontinue

break是强制退出循环,不执行剩下的语句

continue 用于终止某次循环过程,跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定(再次回到寻魂开始的地方,从新开始循环)

image-20240928140648801

标签

image-20240928141308637

打印三角形

image-20240928142449929

方法

Java方法是语句的集合,他们在一起执行一个功能

  • 方法是解决一类问题的步骤的有序组合
  • 方法包含于类或对象中
  • 方法在程序中被创建,在其他地方被引用
  • 方法的本意是功能块
  • 一个方法只完成一个功能

image-20240928191935748

void表示

main方法要时刻保持简介干净,尽量将公共模块都提取到外面,通方法调用来实现功能

image-20240928195152724

方法的定义

Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段

定义方法的语句

方法包含一个方法头和一个方法体

image-20240928200006774

形参和实参

image-20240928202526653

方法调用

调用方法:对象名.方法名(实参列表)

  • 当方法返回一个值得时候,方法调用通常被当作一个值

    int larger = max(30,40);
    
  • 当方法返回值是void,方法调用一定是一条语句

    System.out.println("Hello,Yolo!")
    

image-20240928211748887

方法重载

重载就是在一个类中,有相同的函数名称,但形参不同的函数

方法的重载的规则:

  • 方法名称必须相同
  • 参数列表必须不同(个数不同,或类型不同,参数排列顺序不同等)
  • 方法的返回类型可以相同也可以不同
  • 仅仅返回类型不同不足以成为方法的重载

image-20240929171454189

可变参数(不定项参数)

image-20240929193520659

递归

自己调用自己

递归的两部分

  • 递归头:定义什么时候不调用自身方法。如果没有头,将陷入死循环
  • 递归体:什么时候需要调用自身方法

image-20240929195810357

image-20240929200743571

image-20240929201051691

基数大的不要用递归

计算器

数组

数组是相同类型数据的有序集合,是相同类型的若干个数据,按照一定的先后次序排雷组合而成

其中的每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问他们

格式

dataType[] arrayRefVar;

用 new 来创建数组

定义了什么类型的数组,就new什么类型的数组

dataType[] arrayRefVar = new dataType[arraySize];

eg:

nums = new int [10];			#可以存放10个int类型的数字

image-20240929220817489

内存分析

数组边界

注意下标的合法区间 [0,length-1]超出区间会报错

image-20241007173640671

image-20241007173755943

数组的使用

for循环

image-20241007200142765

反转数组

image-20241008153318298

多维数组

二维数组

int a[][] = new int[2][5];

image-20241008155425775

image-20241008155712066

image-20241008161417004

image-20241008161654473

冒泡排序

  • 比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置

  • 每一次比较,都会产生出一个最大,或者最小的数字;

  • 下一轮则可以少一次排序!

  • 依次循环,直到结束!

image-20241008171733829

自动排序

Arrays.sort(n);

稀疏数组

  • ​ 当一个数组中大部分元素为0,或者为同一值的数组时,可以用稀疏数组来保存数组
  • 稀疏数组的处理方式
    1. 记录数组一共有几行几列,有多少个不同值
    2. 把具有不同值的元素而后行列及值记录爱意额小规模数组中,从而缩小程序的规模

image-20241008201704591

转换为稀疏数组

获取有效值个数

image-20241008203320501

稀疏数组还原

面向对象编程 和 面向过程编程 的区别

面向过程编程是 将任务一步步拆分,第一步干啥,第二步干啥,最后干啥

面向对象编程是 先有对象 然后与其进行互动

GirlFriend gf = new GirlFriend();
gf.name = "Alice";
gf.send("flowers");

创建对象,赋值,调用对象,并传递了个参数 Alice发送了一些 花

面向对象

本质

以类的方式组织代码,以对象的组织(封装)数据

基本概念

  • 实例
  • 方法

三大特性

(面向对象的实现方式)

  • 封装

  • 继承

  • 多态

面向对象基础

Person zhang = new Person();

创建了Person类型的实例,通过变量zhang来指向它

Person zhang是定义Person是定义Person类型的变量zhangnew Person()是创建Person实例

image-20241010201108240

方法

public变成private

外部代码调用方法setName()setAge()来间接修改private字段

setAge()就会检查传入的参数

image-20241010204106305

注:类通过定义方法,可以给外部代码暴露一些操作的接口

定义方法

修饰符 方法返回类型 方法名(方法参数列表) {
    若干方法语句;
    return 方法返回值;
}
private方法

只有内部方法可以调用private方法

image-20241010211847814

以上代码没有定义age字段,获取age时,通过方法getAge()返回的是一个实时计算的值,并非存储在某个字段的值。这说明方法可以封装一个类的对外接口,调用方不需要知道也不关心Person实例在内部到底有没有age字段

this变量

在方法内部调用,始终指向当前实例

没有命名冲突时可以省略

class Person {
    private String name;

    public String getName() {
        return name; // 相当于this.name
    }
}
class Person {
    private String name;

    public void setName(String name) {
        this.name = name; // 前面的this不可少,少了就变成局部变量name了
    }
}
方法参数
class Person {
    ...
    public void setNameAndAge(String name, int age) {
        ...
    }
}

当调用以上方法时,必须调用两个参数, stringint

Person zhang = new Person();
zhang.steNameAndAge("zhangsan",18)
可变参数

可变参数跟数组类型类似

image-20241011215334894

参数绑定

调用方把参数传递给实例方法时,调用时传递的值会按参数位置一一绑定

基本类型的参数传递

image-20241011222206952

以上,setAge方法是将传入的值赋给Person实例的 age属性,变量 n本身与 age属性并没有绑定,所以 当 n值改变时,page属性保持不变

故 基本类型的参数传递 时局部变量和n互不影响

传递引用参数

image-20241012192648660

以上 参数是以一个数组,修改其内容,实例 p 的字段 name的内容 也会被修改

引用类型参数的传递,调用方的变量,和接收方的参数变量,指向的是同一个对象。双方任意一方对这个对象的修改,都会影响对方(因为指向同一个对象)

image-20241012200121161

调用方法

实例变量.方法名("参数")

zhang.setName("李华")

构造方法

创建实例时,通过构造方法实现将实例的值初始化完成

image-20241012202411799

构造方法名是类名,对参数没有限制,在方法内部(跟普通方法象不没有返回值【包括void】)

注:

当我们定义了一个类而没有自定义构造方法时,编译器会自动生成一个默认的构造方法,默认构造方法里 没有参数和执行语句

class Person {
    public Person() {
    }
}

我们还可以定义两个构造方法 比如带参数的和不带参数的

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person("Xiao Ming", 15); // 既可以调用带参数的构造方法
        Person p2 = new Person(); // 也可以调用无参数构造方法
    }
}

class Person {
    private String name;
    private int age;

    public Person() {
    }

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

    public int getAge() {
        return this.age;
    }
}

image-20241012205337665

由于先执行初始化代码 在执行构造函数的代码 ,所以 new Person的值由构造方法确定

多个构造方法
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 = name;
        this.age = 12;
    }

    public Person() {
    }
}

如果调用new Person("Xiao Ming", 20);,会自动匹配到构造方法public Person(String, int)

如果调用new Person("Xiao Ming");,会自动匹配到构造方法public Person(String)

如果调用new Person();,会自动匹配到构造方法public Person()

构造方法调用另一个构造方法
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)
    }
}

方法重载

方法名相同,但参数不同,叫方法重载(Overload)

功能类似的方法,使用同一方法名,调用起来方便

class Hello {
    public void hello() {
        System.out.println("Hello, world!");
    }

    public void hello(String name) {
        System.out.println("Hello, " + name + "!");
    }

    public void hello(String name, int age) {
        if (age < 18) {
            System.out.println("Hi, " + name + "!");
        } else {
            System.out.println("Hello, " + name + "!");
        }
    }
}

可以有多个重载方法

继承

继承机制,可以复用代码

当我们在person类的基础上新增studentstudent类包含了person类已有的字段和方法并且多了sorce字段

class Person {
    private String name;
    private int age;

    public String getName() {...}
    public void setName(String name) {...}
    public int getAge() {...}
    public void setAge(int age) {...}
}

class Student {
    private String name;
    private int age;
    private int score;

    public String getName() {...}
    public void setName(String name) {...}
    public int getAge() {...}
    public void setAge(int age) {...}
    public int getScore() { … }
    public void setScore(int score) { … }
}

根据继承机制 以上代码可以用 extends关键字来实现继承

不需要重新定义agename字段 只需要重新定义score字段

class Person {
    private String name;
    private int age;

    public String getName() {...}
    public void setName(String name) {...}
    public int getAge() {...}
    public void setAge(int age) {...}
}

class Student extends Person {
    private int score;

    public int getScore() { … }
    public void setScore(int score) { … }

注:子类自动获得了父类的所有字段,严禁定义与父类重名的字段!

在OOP的术语中,我们把Person称为超类(super class),父类(parent class),基类(base class),把Student称为子类(subclass),扩展类(extended class

感觉跟ssti的继承类似 每个类都会继承自某个类

image-20241013113757929

也可以 某两个类继承于同一个类

protected关键字

  • 子类无法访问父类的private字段 或者private方法
  • 但是 只要将 private修改为 protected就能被子类访问到
  • 子类的子类 也可以访问其父类的protected
  • protected关键字所修饰的字段和防范 能够保证访问权限在继承树的内部

super(父类)

super表示父类,当子类引用父类的字段时,可以用 super.fileName

class Student extends Person {
    public String hello() {
        return "Hello, " + super.name;
    }
}

除必要情况 也可以直接使用 this.anme或者name 效果是一样的

当父类没有默认的构造方法时 子类就必须调用super();

public class Main {
    public static void main(String[] args) {
        Student s = new Student("Xiao Ming", 12, 89);
    }
}

class Person {
    protected String name;
    protected int age;

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

class Student extends Person {
    protected int score;

    public Student(String name, int age, int score) {
        super(name, age); // 调用父类的构造方法Person(String, int)
        this.score = score;
    }
}

子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,不是继承的

使用sealed修饰class,并通过permits明确写出能够从该class继承的子类名称

public sealed class Shape permits Rect, Circle, Triangle {
    ...
}

向上转型

student继承了 person之后 student就有了 perosn的所有功能 可以实现一个引用类型为 person的变量指向 student类型的实例

Person p = new Student();

通过以上实例 可以发现 子类类型可以转换为更高层次的父类甚至是 object

向下转型

将父类类型强制转换成子类型

Person p1 = new Student();
Student s1 (Student) p1;

但是如果 p2一开始是指向Person的将无法转换

Person p2 = new Person();
Student s2 (Student) p2;
instanceof操作符
Person p = new Person();
System.out.println(p instanceof Person); // true
System.out.println(p instanceof Student); // false

Student s = new Student();
System.out.println(s instanceof Person); // true
System.out.println(s instanceof Student); // true

Student n = null;
System.out.println(n instanceof Student); // false

判断instanceof

 public static void main(String[] args) {
        Object obj = "hello";
        if (obj instanceof String s) {
            // 可以直接使用变量s:
            System.out.println(s.toUpperCase());
        }
    }
}

组合

studentpersonis关系, studentbookhas关系

is关系是继承 has关系是组合

class Student extends Person {
    protected Book book;
    protected int score;
}

多态

在继承关系中,子类如果定义了一个与父类方法签名完全相同的方法,被称为覆写(Override)

class Person {
    public void run() {
        System.out.println("Person.run");
    }
}

在子类Student中,覆写这个run()方法:

class Student extends Person {
    @Override	//编译器会帮助检查是否覆写成功
    public void run() {
        System.out.println("Student.run");
    }
}

计算税收的实例

// Polymorphic
public class Main {
    public static void main(String[] args) {
        // 给一个有普通收入、工资收入和享受国务院特殊津贴的小伙伴算税:
        Income[] incomes = new Income[] {
            new Income(3000),
            new Salary(7500),
            new StateCouncilSpecialAllowance(15000)
        };
        System.out.println(totalTax(incomes));
    }

    public static double totalTax(Income... incomes) {
        double total = 0;
        for (Income income: incomes) {
            total = total + income.getTax();
        }
        return total;
    }
}

class Income {
    protected double income;

    public Income(double income) {
        this.income = income;
    }

    public double getTax() {
        return income * 0.1; // 税率10%
    }
}

class Salary extends Income {
    public Salary(double income) {
        super(income);
    }

    @Override
    public double getTax() {
        if (income <= 5000) {
            return 0;
        }
        return (income - 5000) * 0.2;
    }
}

class StateCouncilSpecialAllowance extends Income {
    public StateCouncilSpecialAllowance(double income) {
        super(income);
    }

    @Override
    public double getTax() {
        return 0;
    }
}

在必要的情况下,我们可以覆写Object的这几个方法。例如:

class Person {
    ...
    // 显示更有意义的字符串:
    @Override
    public String toString() {
        return "Person:name=" + name;
    }

    // 比较是否相等:
    @Override
    public boolean equals(Object o) {
        // 当且仅当o为Person类型:
        if (o instanceof Person) {
            Person p = (Person) o;
            // 并且name字段相同时,返回true:
            return this.name.equals(p.name);
        }
        return false;
    }

    // 计算hash:
    @Override
    public int hashCode() {
        return this.name.hashCode();
    }
}

在子类的覆写方法中,如果要调用父类的被覆写的方法,可以通过super来调用

继承可以允许子类覆写父类的方法。如果一个父类不允许子类对它的某个方法进行覆写,可以把该方法标记为final。用final修饰的方法不能被Override

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

class Student extends Person {
    // compile error: 不允许覆写
    @Override
    public String hello() {
    }
}

如果一个类不希望任何其他类继承自它,那么可以把这个类本身标记为final。用final修饰的类不能被继承:

final class Person {
    protected String name;
}

// compile error: 不允许继承自Person
class Student extends Person {
}

字段同理

class Person {
    public final String name = "Unamed";
}

给final字段重新赋值会报错

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

抽象方法

如果一个class定义了方法,但没有具体执行代码,这个方法就是抽象方法,抽象方法用abstract修饰。

因为无法执行抽象方法,因此这个类也必须申明为抽象类(abstract class)。

接口

interface用 它来声明一个接口

所谓interface,就是比抽象类还要抽象的纯抽象接口,因为它连字段都不能有。因为接口定义的所有方法默认都是public abstract

当一个具体的class去实现一个interface时,需要使用implements关键字。举个例子:

class Student implements Person {
    private String name;

    public Student(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(this.name + " run");
    }

    @Override
    public String getName() {
        return this.name;
    }
}

接口继承

一个interface可以继承自另一个interfaceinterface继承自interface使用extends,它相当于扩展了接口的方法。例如:

interface Hello {
    void hello();
}

interface Person extends Hello {
    void run();
    String getName();
}

此时,Person接口继承自Hello接口,因此,Person接口现在实际上有3个抽象方法签名,其中一个来自继承的Hello接口

image-20241013170726459

静态字段和静态方法

静态字段

public class Main {
    public static void main(String[] args) {
        Person ming = new Person("Xiao Ming", 12);
        Person hong = new Person("Xiao Hong", 15);
        ming.number = 88;
        System.out.println(hong.number);
        hong.number = 99;
        System.out.println(ming.number);
    }
}

class Person {
    public String name;
    public int age;

    public static int number;

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

推荐用类名来访问静态字段

Person.number = 99;
System.out.println(Person.number);

静态方法

静态方法需通过类名调用

静态方法属于class不属于实例

包没有父子关系 没有继承关系

解决包冲突的问题包名.类名,如

小明的Person类存放在包ming下面,因此,完整类名是ming.Person

JDK的Arrays类存放在包java.util下面,因此,完整类名是java.util.Arrays

在定义class的时候,我们需要在第一行声明这个class属于哪个包

小明的Person.java文件:

package ming; // 申明包名ming

public class Person {
}

包作用域

包作用域是指,一个类允许访问同一个 package的没有 publicprivate修饰的 class,以及没有public protected private修饰的字段和方法

位于同一个包的类,可以访问包作用域的字段和方法。不用publicprotectedprivate修饰的字段和方法就是包作用域。例如,Person类定义在hello包下面:

package hello;

public class Person {
    // 包作用域:
    void hello() {
        System.out.println("Hello!");
    }
}

当小明要引用小军的类时

package ming;

// 导入完整类名:
import mr.jun.Arrays;

public class Person {
    public void run() {
        // 写简单类名: Arrays
        Arrays arrays = new Arrays();
    }
}

定义为public的类或者方法可以被其它类调用,前提是要有访问的权力

定义为private的方法无法被其他类访问:

image-20241014203521520

嵌套

定义在 class内部的 class 就是嵌套类

final可以阻止局部变量、方法被重新赋值,方法被子类覆写,class被覆写

内部类

有一种类被定义在另一个类的内部,称为内部类(Inner Class)

class Outer {
    class Inner {
        // 定义了一个Inner Class
    }
}

上述定义的Outer是一个普通类,而Inner是一个Inner Class,它与普通类有个最大的不同,就是Inner Class的实例不能单独存在,必须依附于一个Outer Class的实例。示例代码如下:

// inner class
public class Main {
    public static void main(String[] args) {
        Outer outer = new Outer("Nested"); // 实例化一个Outer
        Outer.Inner inner = outer.new Inner(); // 实例化一个Inner
        inner.hello();
    }
}

class Outer {
    private String name;

    Outer(String name) {
        this.name = name;
    }

    class Inner {
        void hello() {
            System.out.println("Hello, " + Outer.this.name);
        }
    }
}
Outer.Inner inner = outer.new Inner();

想要实例化Inner,我们必须首先创建一个Outer的实例,然后,调用Outer实例的new来创建Inner实例

观察Java编译器编译后的.class文件可以发现,Outer类被编译为Outer.class,而Inner类被编译为Outer$Inner.class

Static Nested Class

最后一种内部类和Inner Class类似,但是使用static修饰,称为静态内部类(Static Nested Class):

// Static Nested Class
public class Main {
    public static void main(String[] args) {
        Outer.StaticNested sn = new Outer.StaticNested();
        sn.hello();
    }
}

class Outer {
    private static String NAME = "OUTER";

    private String name;

    Outer(String name) {
        this.name = name;
    }

    static class StaticNested {
        void hello() {
            System.out.println("Hello, " + Outer.NAME);
        }
    }
}

static修饰的内部类和Inner Class有很大的不同,它不再依附于Outer的实例,而是一个完全独立的类,因此无法引用Outer.this,但它可以访问Outerprivate静态字段和静态方法。如果把StaticNested移到Outer之外,就失去了访问private的权限。

classpath

classpath是JVM用到的一个环境变量,它用来指示JVM如何搜索class

Jar包

将目录打包

字符串和编码

String是一个引用类型

String s1 = "Hello";

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

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

字符串比较

比较两个字符串的内容是否相等 要用equals()方法

public class Main {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";
        System.out.println(s1 == s2);
        System.out.println(s1.equals(s2));
    }
}

索引从零开始

搜索子串的更多的例子:

"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"

去除首尾空白字符

使用trim()方法可以移除字符串首尾空白字符。空白字符包括空格,\t\r\n

"  \tHello\r\n ".trim(); 

使用 isEmpty()isBlank()来判断字符串是否为空和空白字符串

替换字串

要在字符串中替换子串,有两种方法。一种是根据字符或字符串替换:

String s = "hello";
s.replace('l', 'w'); // "hewwo",所有字符'l'被替换为'w'
s.replace("ll", "~~"); // "he~~o",所有子串"ll"被替换为"~~"

另一种是通过正则表达式替换:

String s = "A,,B;C ,D";
s.replaceAll("[\\,\\;\\s]+", ","); // "A,B,C,D"

image-20241014220739424

格式化字符串

字符串提供了formatted()方法和format()静态方法,可以传入其他参数,替换占位符,然后生成新的字符串:

// String
public class Main {
    public static void main(String[] args) {
        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));
    }
}

有几个占位符,后面就传入几个参数。参数类型要和占位符一致。我们经常用这个方法来格式化信息。常用的占位符有:

  • %s:显示字符串;
  • %d:显示整数;
  • %x:显示十六进制整数;
  • %f:显示浮点数。

类型转换

使用 valueof

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

image-20241014221514879

参考链接

posted @ 2024-10-21 21:46  Yolololololo  阅读(8)  评论(0编辑  收藏  举报