java学习

本文最后更新于 2025年4月17日 下午

部分来自吉林大学出版社《零基础学Java》

java学习

String

char[] a和String[] a的区别

char存储单个字符,string存储字符串对象

  • char[] a:数组元素以单个字符的形式存在。例如,{'H', 'e', 'l', 'l', 'o'}
  • String[] a:数组元素以字符串的形式存在。例如,{"Hello", "World"}

String 实例化

可以使用String a = new String('gsbhs');创建String对象

String b = new String(a); 使用已有字符串变量实例化b

1
2
3
char[] charArray = {'a','b','c','d'};
String a = new String(charArray); //利用字符数组实例化 a='abcd'
String a = new String(charArray,1,2); //从字符数组索引1开始,提取2个元素,创建一个字符串

String 连接

只要+操作符的一个操作数是字符串,编译器会自动将另一个操作数转换成String

提取 String 信息

1
2
3
4
5
6
7
str.lenth();   //获取字符串长度
str.charAt(index); //获取字符串str内指定索引index的字符
str.indexOf(substr); //获取字符串str内指定的字符或字符串substr首次出现的索引位置,没检索到则返回-1
str.startsWith(prefix); //判断字符串str是否以指定的前缀prefix开始
str.endsWith(suffix); //判断字符串str是否以指定的后缀suffix结束
str.toCharArray(); //将字符串str转换成一个字符数组
str.contains(string); //判断字符串str内是否包含指定的内容string

字符串操作

  1. 截取字符串

    1
    2
    str.substring(beginIndex);   //返回一个新的字符串,该字符串从指定的索引beginIndex处的字符开始,直到endIndex处的字符。(beginIndex包括,endIndex不包括)
    str.substring(beginIndex,endIndex);
  2. 字符串替换

    1
    str.replace(oldstr,newstr);   //返回一个新的字符串。oldstr为要替换的子字符串,newstr为替换后的子字符串。如果oldstr出现多次,则全部替换;如果没有找到oldstr,则返回原字符串。(oldstr大小写敏感)
  3. 字符串分割

    1
    str.split(regex);   //以regex为分隔符,返回一个String数组。
  4. 大小写转换

    1
    2
    str.toLowerCase();   //字符串中所有字符转换成小写,返回一个新的 String 对象
    str.toUpperCase(); //字符串中所有字符转换成大写,返回一个新的 String 对象
  5. 去除空白内容

    1
    str.trim();   //删除字符串首尾处的空白字符,返回一个新的 String 对象
  6. 比较字符串是否相等

    1
    str.equals(str1);   //当且仅当进行比较的字符串不为null且str和str1内容相同时,结果为true。null和""是2种概念。

StringBuffer类

StringBuffer类是线程安全的可变字符序列,即线程安全的可变字符串。和String本质一样,但执行效率快很多,且创建的字符串序列是可修改的,实体容量会随着存放的字符串增加而自动增加。

  1. 创建StringBuffer类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //创建StringBuffer类必须使用new而不能像String对象那样直接引用字符串常量
    //String类
    // 直接引用字符串常量
    String str1 = "Hello";
    // 使用 new 关键字创建对象
    String str2 = new String("Hello");

    //StringBuffer类
    // 使用 new 关键字创建 StringBuffer 对象
    StringBuffer sbf = new StringBuffer(); //创建一个对象,无初始值
    StringBuffer sbf = new StringBuffer("Hello"); //创建一个对象,初始值为"Hello"
    StringBuffer sb = new StringBuffer(32); //创建一个对象,初始容量为32个字符
  2. append()方法

    1
    sbf.append(obj);   //obj可为任意数据类型的对象,都会转成字符串的表现形式追加到sbf。
  3. setCharAt(int index, char ch)方法

    1
    sbf.setCharAt(idnex,ch);   //将指定索引index处的字符修改为ch
  4. insert(int offset,String str)方法

    1
    2
    sbf.insert(offset,str);   //将字符串str插入到指定的索引值offset位置上。从指定索引[offset]开始向后移,str插进去
    //StringBuilder sbf1=sbf.insert(5, ", Java");先对sbf进行操作,再赋值给sbf1
  5. delete(int start,int end)

    1
    2
    sbf.delete(start,end)   //移除sbf内从索引start开始end结束(不包含)的子字符串。如果end-1超出最大索引范围,则一直到序列尾部。如果start=end,则不发生改变。
    //该方法会直接修改调用它的 StringBuffer 或 StringBuilder 对象,而不是创建一个新的对象。
  6. 其他方法

    有类似String类的用法,如lenth等。。。

java面向对象

类与对象(面向对象编程基础)

1
2
3
4
class 类名称{
//类的成员变量
//类的成员方法
}

成员变量的定义与普通变量的定义一样

成员方法

语法格式
1
2
3
4
[权限修饰符] [返回值类型] 方法名( [参数类型 参数名] ) [throws 异常类型]{
...//方法体
return 返回值;
}

权限修饰符:privatepublicprotected,也可以不写,用于控制方法的访问权限。

返回值类型:用于指定方法返回值的类型,可以是任意类型。如果方法不需要返回值,则使用void关键字。方法如果有返回值,则必须使用return关键字返回一个指定返回值类型的数据。

参数:可有可无。参数可以是对象,也可是变量。

示例:

1
2
3
4
5
6
7
8
9
10
11
//无返回值
public void showGoods() {
System.out.println("库存商品名称:");
System.out.println(FullName);
}

//有返回值
public int showGoods() {
System.out.println("商品库存名称");
return 1; //如果将"return 1;"删除,则会报错"This method must return a result of type int"
}
成员方法的参数

调用方法时传给方法的值叫实参;在方法内部接收实参的变量叫形参。形参只在方法内部有效。

  1. 值参数

    当你将一个参数以值传递的方式传递给函数或方法时,实际上传递的是该参数的一个副本,而不是参数本身。函数或方法内部对这个副本的修改不会影响到原始参数的值。对于基本数据类型,传递的是值的副本;对于引用类型,传递的是引用(内存地址)的副本。

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class Book {
    public static void main(String[] args) {
    Book book = new Book();
    int shelf = 30; //实参
    int box = 40; //实参

    System.out.println("把书架上的书全部放进箱子后,箱子里一共有"
    + book.add(shelf,box) + "本书。\n明细如下:书架上"
    + shelf + "本书,箱子里原有" + box + "本书。");
    }
    private int add(int shelf,int box) { //传形参
    box = box + shelf; //形参
    return box; //输出形参
    }
    }
  2. 引用参数

    给方法传递参数时,参数的类型是数组或其他引用类型,会将修改传递到实参。

  3. 不定长参数

    声明方法时,有若干个相同类型的参数,可以定义为不定长参数。

    1
    权限修饰符 返回值类型 方法名(参数类型... 参数名)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class add {
    // 定义一个可变参数(不定长参数)的加法方法
    public static int add(int... x) {
    int result = 0;
    for (int i = 0; i < x.length; i++) {
    result += x[i];
    }
    return result;
    }

    public static void main(String[] args) {
    // 调用 add 方法并传入参数
    int sum = add(1, 2, 3, 4, 5);
    // 打印计算结果
    System.out.println("这些数的和是: " + sum);
    }
    }

构造方法(类似python的__init__,在创建类的对象时对对象进行初始化,new的时候调用)

特点
  1. 方法名与类名相同

    构造方法的名称必须和所在类的名称完全一致,包含大小写。

    1
    2
    3
    4
    5
    6
    public class Person {
    // 构造方法,方法名与类名相同
    public Person() {
    System.out.println("Person 对象被创建");
    }
    }
  2. 没有返回类型

    构造方法没有返回类型,连 void 也不用写。这是构造方法和普通方法的一个重要区别。普通方法需要明确指定返回类型,如 intString 等。

    1
    2
    3
    4
    5
    6
    7
    8
    public class Student {
    // 构造方法,没有返回类型
    public Student() {
    System.out.println("Student 对象被创建");
    }
    }
    Student student = new Student("John", 25); //开头的Student表示这个实例化的student对象是属于Student类的,类似定义一个String s = "123"
    //java10开始可以通过var自动判断是属于哪个类,即可用var代替Student
  3. 创建对象时自动调用

    当使用 new 关键字创建类的对象时,会自动调用相应的构造方法。构造方法在对象实例化的过程中起到初始化对象的作用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Book {
    public Book() { //方法名和类名同名,为构造方法
    System.out.println("Book 对象被创建并初始化");
    }

    public static void main(String[] args) {
    // 创建 Book 对象,自动调用构造方法
    Book book = new Book();
    }
    }
  4. 可以重载

    和普通方法一样,构造方法也支持重载。也就是说,一个类中可以定义多个构造方法,只要它们的参数列表不同(参数的个数、类型或顺序不同)。通过构造方法重载,可以根据不同的需求来创建对象。

    即java可以创建多个同名但参数列表不同的构造方法。通过不同的参数列表(参数的个数、类型或顺序不同)来确定使用哪个构造方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class Rectangle {
    private int width;
    private int height;

    // 无参构造方法
    public Rectangle() {
    width = 0;
    height = 0;
    }

    // 带一个参数的构造方法
    public Rectangle(int side) {
    width = side;
    height = side;
    }

    // 带两个参数的构造方法
    public Rectangle(int width, int height) {
    this.width = width;
    this.height = height;
    }
    }
  5. 若未定义构造方法,编译器会提供默认构造方法

  6. 可以使用 thissuper 关键字(构造方法接收外部参数,传递给类内部的成员变量,如构造方法Person接收name和age,通过this关键字传递给name和age)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Person {
    String name; //定义成员变量
    int age;

    // 构造方法
    public Person(String name, int age) {
    this.name = name; //传递参数
    this.age = age;
    }
    }

    public class Main {
    public static void main(String[] args) {
    Person person = new Person("John", 25);
    }
    }


定义语法
1
2
3
4
5
6
7
8
9
10
class Book {
public Book(int args) { //构造方法
}
}

class Book {
public Book(int args) { //有参数构造方法
//对成员变量进行初始化
}
}

局部变量

局部变量在方法执行时被创建,执行结束时被销毁。使用前必须先赋值或初始化。

作用域
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class BookTest {
String name; //成员变量
int id = 100; //成员变量

public void setName(String name) { //成员方法
this.name = name;
}

public String getName(){ //成员方法
int id = 0; //局部变量
setName("Java");
return id + this.name;
}

public static void main(String[] args) {
System.out.println(new BookTest().getName()); //必须new BookTest(),因为main是static方法,不能直接在静态方法内部调用非static方法
}
}

//返回 0Java 而不是100java
//成员变量和方法内的局部变量同名时,方法中对这个变量的访问以局部变量为基准
//即方法内部局部变量优先
重复声明的问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//互不嵌套声明局部变量
public void doString(String name) {
int id = 0;
for (int i = 0; i < 10; i++) { //声明局部变量i,作用域为for循环内
System.out.println("......");
}
for (int i = 0; i < 10; i++) { //声明局部变量i,作用域为for循环内
System.out.println("......");
}
}
//不报错


// 嵌套声明局部变量
public void doString(String name) {
int id = 0;
int id = 1;
}
//或
public void doString(String name) {
int id = 0; //这里删除就不会报错了
for (int i = 0; i < 10; i++) {
int id = 1; //for循环内 循环定义变量不会报错,因为for循环内定义的变量的作用域仅为当前循环,超出后自动销毁,不存在同时定义变量
}
}
//报错 java: 已在方法 doString(java.lang.String)中定义了变量 id

this关键字

this可调用成员方法、成员变量和构造方法。

当成员变量和局部变量同名时,会优先使用局部变量,成员变量可通过this关键字使用。

1
2
3
4
5
6
7
public class BookTest {
String name; //成员变量

public void setName(String name) { //成员方法
this.name = name;
}
}

this也可以被返回

1
2
3
4
5
public class Book {
public getBook() {
return this; //将Book类的对象进行返回
}
}

this也可以调用类中的构造方法(this()语句前不可以有其他代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class EggCake {
int eggCount;
public EggCake(int eggCount) {
this.eggCount = eggCount;
System.out.println("这个鸡蛋灌饼里有" + eggCount + "个蛋。")
}

public EggCake() {
this(1); //this返回的是类的对象,即new EggCake,加了括号是new EggCake(1),所以new EggCake()即new EggCake(1)。
}

public static void main(String[] args) {
EggCake cake1 = new EggCake();
EggCake cake1 = new EggCake(5);
}
}

在静态方法里不能使用 this 关键字。因为 this 依赖于对象实例,而静态方法可以在没有创建对象实例的情况下直接调用。可以使用类名.静态/局部变量

静态方法

静态方法里不能使用this:

Java 程序运行时,当一个类被加载进 JVM(Java 虚拟机)时,静态方法就已经被分配好了内存空间,可直接通过类名调用,它的存在不依赖于类的实例化。也就是说,即使没有创建该类的任何实例,静态方法也能正常使用。而 this 关键字代表当前对象的引用,其存在的前提是有类的实例,没有创建实例就不能使用,因此静态方法里不能有this

静态方法里不能直接使用非静态变量和非静态方法:

静态方法属于类本身,不依赖于类的实例,在类加载时就已经存在。而静态变量同样属于类,在类加载时初始化,被该类的所有实例共享。因此,静态方法可以直接调用静态变量,但不能直接调用非静态变量,因为非静态变量是与类的实例相关联的,每个实例可能有不同的值。而静态方法在类加载时就存在,此时可能还没有创建类的实例,无法确定要访问哪个实例的非静态变量,因此不能直接调用非静态变量。静态方法里不能使用非静态方法同理。

总结:静态方法里可以使用静态变量和局部变量,不能使用this关键字,可实例化一个对象再调用这个对象内的方法或变量。

使用场景

如果想使用类中的成员方法,需要先将这个类进行实例化。使用静态方法无需创建对象实例,方便调用。

调用语法
1
类名.静态方法();
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class BookTest {
String name; //成员变量

public String setName(String name) { //成员方法 非静态 属于实例
this.name = name;
return name;
}

public static void main(String[] args) {
System.out.println(new BookTest().setName("xixinyy")); //setName为非静态方法,必须实例化类后再调用
}
}


public class BookTestStatic {

static String name; //静态成员变量,属于类,去掉static会报错,静态方法可以直接调用静态变量和局部变量,不能直接调用非静态变量

public static String setName(String name) { //成员方法 静态 属于类
BookTestStatic.name = name; //不能使用this,this依赖于实例,静态方法产生时类还没被实例化
return name;
}

public static void main(String[] args) {
System.out.println(BookTestStatic.setName("xixinyy")); //setName为静态方法,无需实例化即可调用
}

}

静态代码块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class StaticTest {
static String name;

//静态代码块
static {
System.out.println(name + "静态代码块");
};

//非静态代码块
{
System.out.println(name + "非静态代码块");
};

//构造方法
public StaticTest(String a) {
name = a;
System.out.println(name + "构造方法");
};

//成员方法
public void method() {
System.out.println(name + "成员方法");
};

public static void main(String[] args) {
StaticTest test1; //声明一个 StaticTest 类型的变量
StaticTest test2 = new StaticTest("test2"); //创建一个 StaticTest 对象,并将对象的引用赋值给 test2 变量
StaticTest test3 = new StaticTest("test3"); //创建一个 StaticTest 对象,并将对象的引用赋值给 test3 变量
test3.method();
}
}

//null静态代码块
//null非静态代码块
//test2构造方法
//test2非静态代码块
//test3构造方法
//test3成员方法
  • **静态代码块属于类,在类被加载时执行,所以只执行一次。**静态代码块的目的是为类的静态成员变量进行初始化操作,或者执行一些只需要在类加载时执行一次的操作,比如加载配置文件、初始化数据库连接池等。由于类在整个 JVM 生命周期内只会被加载一次,所以静态代码块也只会执行一次。
  • 非静态代码块属于类的实例,所以每次创建对象时,非静态代码块都会执行一次。非静态代码块会在构造方法之前运行。
  • 构造方法在创建对象时运行。
  • **在内存中,静态变量只有一份拷贝,被类的所有实例共享,无论通过类名还是类的某个实例来访问和修改静态变量,都是对内存中同一份静态变量进行操作。所以,当在某个实例里修改静态变量的值时,这个修改会立即反映到类以及该类的其他所有实例中。**所以第二个实例test3返回test2非静态代码块
  • 成员方法只有在使用对象调用时才会运行。

类的主方法

1
2
3
public static void main(String[] args) {
//方法体
}
  • **主方法是静态的。**所以在主方法调用其他方法时,其他方法也必须时静态的。
  • 主方法没有返回值。
  • **主方法的形参为数组。**可以使用args.length获取参数的个数。

面向对象核心技术

类的封装

类的继承

基本思想

基于某个父类的扩展,制定一个新的子类。子类可以继承父类原有的属性和方法,也可增加原来父类所不具备的属性和方法,或者直接重写父类中的某些方法。

extends 关键字

让一个类继承另一个类需要使用extends关键字。

1
2
//语法
Child extends Parents

一个类只可以有一个父类。

1
2
Child extends Parents1,Parents2{   //错误的继承语法
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 定义四边形类
class Quadrilateral {
int side = 4;
void show() {
System.out.println("这是一个四边形");
}
}

// 定义平行四边形类,继承自四边形类
class Parallelogram extends Quadrilateral {
Boolean Parallel = true;
void show() {
System.out.println("这是一个平行四边形");
}
}

class Main1 {
public static void main(String[] args) {
// 创建四边形对象
Quadrilateral quad = new Quadrilateral();
quad.show();
System.out.println("有"+quad.side+"条边");

// 创建平行四边形对象
Parallelogram para = new Parallelogram();
para.show();
System.out.println("有"+para.side+"条边,是否平行:"+para.Parallel);

}
}

//这是一个四边形
//有4条边
//这是一个平行四边形
//有4条边,是否平行:true

重写父类方法时,方法的权限只能从小范围到大范围改变。

super 关键字

super 关键字代表父类对象,可以在子类重构父类的方法或属性后调用父类的方法或属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Quadrilateral {
int side = 4;
void show() {
System.out.println("这是一个四边形");
}
}

class Parallelogram extends Quadrilateral {
void show() {
System.out.println("这是一个平行四边形");
System.out.println(super.side); //调用父类的属性
super.show(); //调用父类的方法
}

public static void main(String[] args) {
// 创建平行四边形对象
Parallelogram para = new Parallelogram();
para.show();
}
}

//这是一个平行四边形
//4
//这是一个四边形
所有类的父类——Object
  • getClass()方法

    1
    2
    getClass().getName();
    //getClass()方法会返回某个对象执行时的Class实例,然后通过Class实例调用getName()方法获取类的名称
  • toString()方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Hello {
    public String toString() {
    return "Say" + getClass().getName() + "to Java";
    }
    public static void main(String[] args) {
    System.out.println(new Hello());
    }
    }

    //toString()方法会返回某个对象的字符串表示形式,当打印某个类对象时,将自动调用重写的toString()方法
  • equals()方法

比较2个对象的引用地址是否相等。

1
2
3
4
5
6
7
8
//用法
对象1.equals(对象2)

String s1 = "123456";
String s2 = "123456";
System.out.println(s1.equals(s2));

//true

java学习
http://page.ccnyy.top/2025/04/01/java/
作者
ccnyy
发布于
2025年4月1日
更新于
2025年4月17日
许可协议