JAVA基础

45 阅读13分钟

JDK、JRE、JVM

  • JRE 是 JDK 的一部分:JDK 是 Java 开发工具包,它包含了 JRE 和一系列开发工具

  • JRE 是 Java 运行时的环境,提供了运行 Java 程序所必需的所有组件,包括 Java 虚拟机(JVM)、Java 核心类库以及支持文件。

  • 如果只是希望运行已有的 Java 程序,那么只需要安装 JRE 即可。但如果要开发 Java 程序,则需要安装 JDK,因为它提供了编译、调试和运行 Java 程序的工具和环境。

  • JDK 用于开发,JRE 用于运行:JDK 主要用于开发人员进行 Java 程序的开发,它提供了编译器(javac)、调试器(jdb)等工具,方便开发人员编写、编译和调试 Java 代码。而 JRE 则是为了让用户能够运行 Java 程序而设计的。当用户双击一个 Java 应用程序(如.jar 文件)时,系统会调用 JRE 来启动 JVM,然后由 JVM 加载并执行 Java 程序。

  • 当启动一个 Java 程序时,JVM 会首先根据类路径查找并加载程序的主类。然后,JVM 会为该类分配内存空间,初始化类的静态变量等。接着,JVM 会调用主类的main方法,开始执行程序。在程序执行过程中,JVM 会按照字节码的指令顺序依次执行各个操作,涉及到对象的创建、方法的调用、运算的执行等。同时,JVM 会监控程序的运行状态,进行内存管理和垃圾回收等操作,以保证程序的稳定运行。

JAVA的数据类型

基本数据类型

  • 整数类型
    • byte:8 位有符号整数,取值范围是 -128 到 127,常用于表示字节数据或在内存空间紧张时存储较小的整数。
    • short:16 位有符号整数,取值范围是 -32768 到 32767,适用于表示较小范围的整数,如数组的索引等。
    • int:32 位有符号整数,取值范围是 -2147483648 到 2147483647,是最常用的整数类型,用于大多数整数运算场景。
    • long:64 位有符号整数,取值范围是 -9223372036854775808 到 9223372036854775807,当需要表示较大的整数,超出int类型的范围时使用。
  • 浮点数类型
    • float:32 位单精度浮点数,用于表示小数,其精度有限,适用于对精度要求不高且需要节省内存空间的场景。
    • double:64 位双精度浮点数,是 Java 中默认的浮点数类型,精度较高,常用于大多数需要处理小数的计算场景。
  • 字符类型
    • char:16 位无符号字符,用于表示单个字符,它采用 Unicode 编码,可以表示世界上大多数语言中的字符。
  • 布尔类型
    • boolean:只有truefalse两个值,用于表示逻辑判断的结果,如条件判断、循环控制等场景。

引用数据类型

  • 类(class):是 Java 中最基本的引用数据类型,用于定义对象的行为和属性。例如,String类用于表示字符串,Integer类用于包装整数等。通过类可以创建多个对象实例,每个对象都有自己的属性值和方法调用。
  • 接口(interface):定义了一组抽象方法和常量,实现接口的类必须实现接口中的所有方法。接口常用于定义规范和契约,使得不同的类可以遵循相同的接口来实现特定的功能。
  • 数组:是一种容器类型,用于存储多个相同类型的数据元素。数组可以是一维数组、二维数组或多维数组,例如int[] arr = {1, 2, 3}定义了一个一维整数数组。
  • 枚举(enum):是一种特殊的数据类型,用于定义一组具有固定取值的常量。例如,定义一个表示星期的枚举类型enum Weekday { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }

逻辑运算符

  • & 见false则为false
  • | 见true则为true
  • ^ 相同为false,不同为true
  • ! 取反
  • && 见false则为false,如果左边的表达式为true,右边的表达式会继续运算。 如果左边的表达式为false,右边的表达式不会继续运算。
  • || 见true则为true, 如果左边的表达式为true,右边的表达式不会继续运算。如果左边的表达式为false,右边的表达式不会继续运算
  • 三元运算符“条件表达式?表达式1:表达式2”

img

基础语法

  • 定义:类是一种抽象的数据类型,是对现实世界中具有相同属性和行为的事物的抽象描述。它定义了一组属性(成员变量)和方法,用于描述对象的状态和行为。
  • 作用:类是创建对象的模板,通过类可以创建多个具有相同属性和行为的对象实例。每个对象都有自己独立的属性值,但共享类中定义的方法。例如,定义一个Car类,它具有color(颜色)、brand(品牌)等属性,以及start()(启动)、stop()(停止)等方法。通过Car类可以创建不同的汽车对象,如红色的宝马车、黑色的奔驰车等,每个对象都有自己的颜色和品牌属性,但都可以调用start()stop()方法来实现汽车的启动和停止功能。

方法

  • 定义:方法是类中定义的一段可执行代码,用于实现特定的功能。它由方法签名(方法名、参数列表)和方法体组成。

  • 作用:方法可以将复杂的业务逻辑封装起来,提高代码的复用性和可维护性。通过调用方法,可以在不同的地方执行相同的代码逻辑,避免代码重复。例如,在Car类中的start()方法,其方法体中可以包含启动汽车所需的一系列操作,如启动发动机、检查仪表盘等。当需要启动汽车时,只需调用car.start()方法即可,而无需在每个需要启动汽车的地方都编写相同的启动代码。

    img

方法的重载

  • 定义:在同一个类中,可以定义多个同名的方法,但这些方法的参数列表必须不同(参数的个数、类型或顺序不同),这就是方法的重载。
  • 作用:方法重载使得在一个类中可以使用相同的方法名来实现不同的功能,根据传递的参数不同来调用不同的方法实现,提高了代码的可读性和灵活性。例如,在一个Calculator类中,可以定义多个add方法来实现不同类型数据的加法运算,如add(int num1, int num2)用于两个整数相加,add(double num1, double num2)用于两个浮点数相加,add(int num1, int num2, int num3)用于三个整数相加。通过方法重载,在调用add方法时,编译器会根据传递的参数类型和个数来确定调用哪个具体的add方法,方便了程序员对不同类型数据的加法操作。

img

封装-this关键字

Student类

package 封装;

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

    public void setName(String name) {
        name = name;
    }
    
    public String getName() {
        return name;
    }
    
    public void setAge(int a) {
        if (a < 0) {
            System.out.println("您输入的年龄有误!!!");
            return;
        }
        age = a;
    }
    
    public int getAge() {
        return age;
    }
    
    public void show() {
        System.out.println("name=" + name + ", " + "age=" + age);
    }

}

main类

package 封装;

public class class_1 {
    public static void main(String[] args){
        Student student=new Student();
        student.setName("奥特曼");
        student.setAge(18);
        student.show();
    }
}

封装

  • 定义:封装是将对象的属性和实现细节隐藏起来,仅对外提供公共的访问接口。通过将数据和操作数据的方法封装在一个类中,可以实现信息的隐藏和保护,防止外部对对象内部状态的直接访问和修改。
  • 优点
    • 数据安全性:通过将属性设置为私有(使用private关键字),只能在类的内部进行访问和修改,外部无法直接操作对象的属性,从而保证了数据的完整性和一致性,避免了数据被非法修改。
    • 代码可维护性:将相关的属性和方法封装在一个类中,使得代码的结构更加清晰,易于理解和维护。当需要对类的内部实现进行修改时,只需要在类的内部进行调整,而不会影响到其他使用该类的代码。
    • 提高复用性:封装好的类可以在不同的地方被重复使用,只要通过类的公共接口来访问和操作对象即可,提高了代码的复用性。

this关键字

  • 指代当前对象this关键字代表当前正在执行方法的对象。在类的方法中,可以使用this来访问当前对象的属性和方法。例如,在一个Person类中有name属性和setName(String name)方法,在setName方法中可以使用this.name = name来将传入的参数值赋给当前对象的name属性,这里的this.name就是指当前对象的name属性,而参数name是方法传入的局部变量。
  • 调用本类的构造方法:在一个构造方法中,可以使用this关键字来调用本类的其他构造方法。这样可以在不同的构造方法之间实现代码复用,避免重复编写相同的初始化代码。例如,在Person类中有多个构造方法,一个是带有姓名和年龄参数的构造方法,另一个是只带有姓名参数的构造方法,只带有姓名参数的构造方法可以通过this(name, 0)来调用带有姓名和年龄参数的构造方法,将年龄初始化为 0。
  • 防止局部变量和成员变量重名:当方法中的局部变量与类的成员变量同名时,使用this关键字可以明确地指定访问的是成员变量,而不是局部变量。例如,在Person类的setName方法中,如果没有this关键字,name = name这样的语句会将方法传入的局部变量name赋值给自己,而不会修改对象的成员变量name,使用this.name = name就可以正确地将传入的参数值赋给对象的成员变量name

String类

Java 中的String类用于表示字符串,它是不可变的,即一旦创建,其内容就不能被修改。String类提供了丰富的方法。

  • length():返回字符串的长度,即字符串中字符的个数。例如,"hello".length()的结果为5
  • charAt(int index):返回字符串中指定索引位置的字符,索引从0开始。如"world".charAt(1)会返回字符'o'
  • equals(Object obj):比较两个字符串的内容是否相等,区分大小写。例如,"java".equals("Java")的结果为false"java".equals("java")的结果为true
  • equalsIgnoreCase(String anotherString):比较两个字符串的内容是否相等,不区分大小写。"Java".equalsIgnoreCase("java")的结果为true
  • substring(int beginIndex):返回从指定索引位置开始到字符串末尾的子字符串。比如"example".substring(3)会返回"ample"
  • substring(int beginIndex, int endIndex):返回从指定起始索引(包含)到结束索引(不包含)的子字符串。例如,"example".substring(1, 4)的结果是"xam"
  • concat(String str):将指定字符串连接到当前字符串的末尾,返回一个新的字符串。如"Hello".concat(" World")会得到"Hello World"
  • split(String regex):根据指定的正则表达式将字符串拆分成字符串数组。例如,"a,b,c".split(",")会返回["a", "b", "c"]
  • trim():去除字符串两端的空白字符(包括空格、制表符等),返回处理后的字符串。比如" java ".trim()的结果是"java"
  • toLowerCase():将字符串中的所有字符转换为小写,返回新的字符串。"Hello".toLowerCase()会得到"hello"
  • toUpperCase():将字符串中的所有字符转换为大写,返回新的字符串。"hello".toUpperCase()会返回"HELLO"

String

  • 不可变性String类是不可变的,一旦创建,其内容就不能被修改。任何对String对象的修改操作都会创建一个新的String对象。例如,当执行str = str + "world"时,实际上会创建一个新的字符串对象,将原来str的值和"world"拼接后赋值给新的str
  • 内存分配:字符串常量存储在字符串常量池中,当创建一个新的字符串常量时,会先在常量池中查找是否已存在相同内容的字符串,如果存在则直接返回引用,否则创建新的字符串对象并放入常量池。这种机制可以提高字符串的使用效率,节省内存空间。
  • 适用场景:适用于处理固定不变的字符串,例如配置文件中的字符串、字符串常量等。由于其不可变性,在多线程环境下是安全的,多个线程可以共享同一个String对象而不会出现数据不一致的问题。

StringBuffer

  • 可变字符串StringBuffer是可变字符串类,它允许对字符串进行修改,而不会创建新的对象。可以通过appendinsertdelete等方法对字符串进行动态操作。例如,使用sb.append("world")可以直接在StringBuffer对象sb的末尾添加字符串"world"
  • 线程安全StringBuffer是线程安全的,它的方法都被synchronized关键字修饰,这意味着在多线程环境下,多个线程可以安全地访问和修改同一个StringBuffer对象,不会出现数据冲突的情况。
  • 适用场景:适用于在多线程环境下对字符串进行频繁修改的场景,如多个线程同时向一个字符串缓冲区中写入数据。

StringBuilder

  • 可变字符串:与StringBuffer类似,StringBuilder也是可变字符串类,提供了丰富的方法来对字符串进行修改操作。例如,可以使用sbuilder.insert(0, "Hello ")StringBuilder对象sbuilder的指定位置插入字符串"Hello "
  • 非线程安全StringBuilder是非线程安全的,它的方法没有synchronized关键字修饰,因此在多线程环境下,如果多个线程同时访问和修改同一个StringBuilder对象,可能会导致数据不一致的问题。
  • 适用场景:适用于单线程环境下对字符串进行频繁修改的场景,由于没有线程同步的开销,其性能比StringBuffer略高。例如,在一个单线程的字符串处理程序中,可以使用StringBuilder来高效地构建和修改字符串。

标准JavaBean类

1.类名需要见名知意

2.成员变量使用private修饰

3.提供至少两个构造方法

​ 3.1 无参数构造

​ 3.2 带全参数构造

4.成员方法

​ 4.1 提供每一个成员变量对应的setXxx() / getXxx()

​ 4.2 如果还有其他行为,也需要写上

快捷键 alt + insert 例如:

public class Student {
    // 成员变量使用private修饰
    private String name;
    private int age;
    private String studentId;

    // 无参数构造方法
    public Student() {
    }

    // 带全参数构造方法
    public Student(String name, int age, String studentId) {
        this.name = name;
        this.age = age;
        this.studentId = studentId;
    }

    // 针对name成员变量的get和set方法
    public String getName() {
        class student{

        }
        return name;
    }

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

    // 针对age成员变量的get和set方法
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    // 针对studentId成员变量的get和set方法
    public String getStudentId() {
        return studentId;
    }

    public void setStudentId(String studentId) {
        this.studentId = studentId;
    }

    // 自定义行为方法:获取学生的基本信息
    public String getStudentInfo() {
        return "姓名:" + name + ",年龄:" + age + ",学号:" + studentId;
    }
}