Java 入门总结 - Zhangyao719/java-study GitHub Wiki

一、变量

八种基本类型

数据类型 关键字 内存占用 示例 取值范围
字节型 byte 1个字节 byte num1 = 127; -128 至 127
短整型 short 2个字节 short num2 = 1000; -32768 至 32767
整型 int(默认) 4个字节 int num3 = 10000; -231 至 231-1, -2147483648 至 2147483647
长整型 long 8个字节 long num4 = 99999L; -263 至 263-1 19位数字 -9223372036854775808 至 9223372036854775807
单精度浮点数 float 4个字节 float num5 = 2.5F; 1.4013E-45 至 3.4028E+38
双精度浮点数 double(默认) 8个字节 double num6 = 2.5; 4.9E-324 至 1.7977E+308
字符型(字面量) char 2个字节 char num7 = 'A'; 0 至 216-1
布尔类型 boolean 1个字节 boolean num8 = true; true,false

类型装换

小范围可以自动赋值给大范围:int → short → int → long → float → double

char 字面量可以转成对应的 ASCⅡ 码对应的数字,赋值给 int

byte a = 127;
int b = a;
System.out.println(b); // 自动转成了 int 类型的 127

char ch = 'b';
int it = ch;
System.out.println(it); // 98  ASCⅡ 码
byte a = 10;
int b = 20;
long c = 30;
long res = a + b + c; // 最终结果由最高类型决定

byte d = 110;
byte e = 120;
// byte f = d + e // 报错
int f = d + e; // 在表达式中,byte、short、char 直接转换成 int 类型参与运算(防止溢出)
int a = 20;
byte b = (byte) a; // 强制类型转换

int i = 1500;
byte j = (byte) i; // -36,溢出(能转,但是可能会算错)

运算符

int a = 5;

// 应算尽算
System.out.println("abc" + a); // "abc5"
System.out.println(5 + a); // 10
System.out.println("abc" + a + 'b'); // "abc5b"
System.out.println(a + 'b' + "abc"); // "103abc",由 5+98+"abc" 得来

二、数组

// 静态初始化
int[] arr1 = new int[]{1,2,3,4,5};
// 简化:
int[] arr2 = {1,2,3,4,5};

// 动态初始化
String[] arr3 = new String[3]; // [3] 代表数组的长度

三、方法

定义与调用

public class Method {
    public static void main(String[] args) {
        int res = sum(1, 2);
        System.out.println(res);
    }
    
    public static int sum(int a, int b) {
        return a + b;
    }
}

可变参数

  1. 格式 数据类型...参数名称
  2. 接收数据非常灵活,可以不传数据、也可以传一个或多个数据、也可以传一个数组;
  3. 可变参数在方法内部就是一个数组;
  4. 可变参数在形参列表中只能出现一个;
  5. 可变参数必须放在参数列表中的最后;
public class Test {
    public static void main(String[] args) {
        fn();
        fn(10);
        fn(10, 20, 30);
        fn(new int[]{1, 2, 3});
    }

    public static void fn(int...args) {
        System.out.println("个数: " + args.length);
        System.out.println("内容 " + Arrays.toString(args));
        // 个数: 0 内容 []
        // 个数: 1 内容 [10]
        // 个数: 3 内容 [10, 20, 30]
        // 个数: 3 内容 [1, 2, 3]
    }
}

方法的重载

一个类中出现多个同名方法,但是形参列表(格数、类型、顺序)不同,这些方法就成为方法重载(overload)

public class MethodOverload {
    public static void main(String[] args) {
        fire();
        fire("日本");
        fire("美国", 2);
    }

    public static void fire() {
        System.out.println("默认向小日本发射导弹");
    }

    public static void fire(String location) {
        System.out.println("向" + location + "发射导弹");
    }

    public static void fire(String location, int num) {
        System.out.println("向" + location + "发射" + num + "枚导弹");
    }
}

四、面向对象

类的定义

// Person
public class Person {
    // 成员变量(属性)
    String name;
    int age;

    //成员方法(行为)
    public void eat(){
        System.out.println("人要干饭");
    }

    public void drink(){
        System.out.println("人要喝水");
    }
}

创建实例化对象

  1. new关键字创建实例;
  2. 使用首字母大写的类名来申明实例;
  3. 给属性添加值
// ObjectOriented
public class ObjectOriented {
    public static void main(String[] args) {
        //原始方式
        Person p = new Person();
        p.name = "金莲";
        System.out.println(p.name);
        p.eat();

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

        //匿名对象
        new Person().eat();
        new Person().name = "大郎";
        System.out.println(new Person().name);//null
    }
}

this

在当前实例的方法内,可以使用 this 来访问当前实例对象上的属性。

public class Student {
    double score;

    public void examine(double cutOff) {
        if(this.score >= cutOff) {
            System.out.println("及格");
        } else {
            System.out.println("不及格");
        }
    }
}

构造器

  1. 构造器函数名必须与类名一致;
  2. 没有返回值参数类型;
  3. 创建对象时,会调用构造器,此时可以为对象属性赋值;
  4. 类自带无参数构造器,默认会被手写的有参构造器覆盖(除非自己手动再写一个无参构造器)
public class Student {
    String name;
    int age;
    double height;
    
    // 无参构造器(默认自带)
    public Student() {
        
    }

    // 有参数构造器
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

// package -----------------------
public class Demo {
    public static void main(String[] args) {
        Student s1 = new Student("林志玲", 18);
    }
}

封装

  1. 使用private,让成员变量私有化,只能被定义它的类访问
  2. 使用public,提供公开的、可访问内部属性的方法;
public class Girl {
    String name;
    private int age ;
    double height;
    double weight;

    // 提供 public 方法设置私有属性
    public void setAge(int age) {
        if (age <= 0) {
            System.out.print("年龄错误");
        } else {
            this.age = age;
        }
    }

    // 提供 public 方法访问私有属性
    public int getAge() {
        return age;
    }
}

实体类 JavaBean

  1. 成员变量全部私有化;
  2. 提供相应的 getXxx、setXxx 方法;
  3. 类中必须有一个公共的无参构造器;
public class Student {
    // 私有成员变量
    private String name;
    private int age;
    private double score;

    // 提供无参构造器(默认自带)
    public Student() {
        
    }

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    // 提供 get、set 方法
     public String getName() {
         return name;
     }

    public void setName(String name) {
        this.name = name;
    }
}

作用:实体类的对象只负责存取数据,而对于数据的业务处理则交给另一个类的对象来处理,这属于设计中的数据与业务分层思想

五、常用 API

package 包

建包

package com.aa.pkg; // 包名

public class Student {
    
}

使用包

  1. 自己同一 package 下的 class 可以直接调用;
  2. 调用其他 package 下的 class 需要导入;
package com.bb.pkg;

// 1. 导入 com.aa.pkg 模块下的 Student 类
import com.aa.pkg.Student;

public class Demo {
    public static void main(String[] args) {
        // 2. 使用 Student 类
        Student s1 = new Student()
    }
}
  1. 调用 Java 提供的程序需要先导包才可以使用;
package com.bb.pkg;

// 1. 导入 java 提供的包
import java.util.Random;

public class Demo {
    public static void main(String[] args) {
        // 使用 Random
        Random = new Random()
    }
}
  1. 调用 Java.lang 包下的程序不需要导包,可以直接使用;
  2. 如果要调用多个不同包下的程序,而这些程序的名称正好一样,此时默认只能导入一个程序,其他的必须带包名访问;
package com.bb.pkg;

import com.aa.User;
import com.cc.User;

public class Demo {
    public static void main(String[] args) {
        // 使用 Random
        Random = new Random();
    }
}

String

创建字符串

public class Demo {
    public static void main(String[] args) {
        String s1 = "张三";

        String s2 = new String(); // s2 = ""

        String s3 = new String("李四"); // s2 = ""

        char[] chars = {'a', 'b', '王', '五'};
        String s4 = new String(chars); // s4 = "ab王五"

        byte[] bytes = {97, 98, 99, 65, 66, 67};
        String s5 = new String(bytes); // s5 = "abcABC"
    }
}

字符串常用方法

<https://www.runoob.com/manual/jdk11api/java.base/java/lang/String.html>

方法名 介绍
charAt(index) 返回指定索引处的 <font style="color:rgb(71, 71, 71);">char</font>值。
toCharArray 将此字符串转换为新的字符数组。
equals ★★★★★ 将此字符串与指定的对象进行比较。 当且仅当参数不是<font style="color:rgb(71, 71, 71);">null</font>且是<font style="color:rgb(71, 71, 71);">String</font>对象表示与此对象相同的字符序列时,结果为<font style="color:rgb(71, 71, 71);">true</font>
equalsIgnoreCase 将此<font style="color:rgb(71, 71, 71);">String</font>与另一个<font style="color:rgb(71, 71, 71);">String</font>比较,忽略了大小写。 如果两个字符串具有相同的长度并且两个字符串中的相应字符等于忽略大小写,则认为它们是相等的忽略大小写。
substring 返回一个字符串,该字符串是此字符串的子字符串。 子字符串以指定索引处的字符开头,并延伸到此字符串的末尾。
replace 返回从替换所有出现的导致一个字符串<font style="color:rgb(71, 71, 71);">oldChar</font>在此字符串<font style="color:rgb(71, 71, 71);">newChar</font>
contains 当且仅当此字符串包含指定的char值序列时,才返回true。
startsWith 测试此字符串是否以指定的前缀开头。
endsWith 测试此字符串是否以指定的后缀结尾。
split 按指定字符切割

部分示例:

String s1 = new String("张三");
String s2 = new String("张三");

System.out.println(s1 == s2); // false 地址不一样
System.out.println(s1.equals(s2)); // true 只要内容一样就为 true

String s3 = new String("aaa");
String s4 = new String("AAA");

System.out.println(s3.equals(s4)); // false
System.out.println(s3.equalsIgnoreCase(s4)); // true 忽略大小写,适合模糊搜索
String s1 = new String("abcdef");
s1.substring(0, 2); // 包前不包后 "ab"
s1.substring(3); // "def"
String s1 = new String("傻逼,垃圾");
s1.replace("傻逼", "**").replace("垃圾", "**");
String s1 = new String("张三,李四,王五");
String names = s1.split(","); // ["张三", "李四", "王五"]

不可变字符串对象

String 的对象是不可变字符串对象。双引号""字符串存储在堆内存的字符串常量池中。

String s1 = new String("张三");
String s2 = new String("张三");
s1 == s2; // false 在堆内存中有两个不同地址的"张三"

String s3 = "李四";
String s4 = "李四";
s3 == s4; // true,"李四" 在堆内存常量池中只存储一份

String s5 = "abc";
String s6 = "ab";
String s7 = s6 + "c";
s5 == s7; // false 因为是变量,无法提前判断

String s8 = "a" + "b" + "c"; // 在编译时,直接转换成了 "abc"
s5 == s8; // true

ArrayList 集合

一般用于存储对象

https://www.runoob.com/manual/jdk11api/java.base/java/util/ArrayList.html

方法名 说明
public boolean add(E e) 将指定的元素添加到此集合的末尾
public void add(int index, E element) 在此集合中的指定位置插入指定的元素
public E get(int index) 返回指定索引处的元素
public int size() 返回集合中的元素的个数
public E remove(int index) 删除指定索引处的元素,返回被删除的元素
public boolean remove(Object o) 删除指定的元素,返回删除是否成功
public E set(int index, E element) 修改指定索引处的元素,返回被修改的元素
public Demo {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList();
        list.add("abc");
        list.add("aabc");
        list.add("bcd");
        list.add("bcda");
        list.add("bcaa");

        // 需求:删除含有 a 的元素
        // bug: 正向删除,元素删除后,后面的会补上,索引后移,可能会出现删不干净的情况
        // bugfix:反向删除
        for(int i = list.size() - 1; i >= 0 ; i--) {
            String name = list.get(i);
            if (name.contains("a")) {
                list.remove(name);
            }
        }
    }
}
⚠️ **GitHub.com Fallback** ⚠️