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:只有
true和false两个值,用于表示逻辑判断的结果,如条件判断、循环控制等场景。
- boolean:只有
引用数据类型
- 类(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”
基础语法
类
- 定义:类是一种抽象的数据类型,是对现实世界中具有相同属性和行为的事物的抽象描述。它定义了一组属性(成员变量)和方法,用于描述对象的状态和行为。
- 作用:类是创建对象的模板,通过类可以创建多个具有相同属性和行为的对象实例。每个对象都有自己独立的属性值,但共享类中定义的方法。例如,定义一个
Car类,它具有color(颜色)、brand(品牌)等属性,以及start()(启动)、stop()(停止)等方法。通过Car类可以创建不同的汽车对象,如红色的宝马车、黑色的奔驰车等,每个对象都有自己的颜色和品牌属性,但都可以调用start()和stop()方法来实现汽车的启动和停止功能。
方法
-
定义:方法是类中定义的一段可执行代码,用于实现特定的功能。它由方法签名(方法名、参数列表)和方法体组成。
-
作用:方法可以将复杂的业务逻辑封装起来,提高代码的复用性和可维护性。通过调用方法,可以在不同的地方执行相同的代码逻辑,避免代码重复。例如,在
Car类中的start()方法,其方法体中可以包含启动汽车所需的一系列操作,如启动发动机、检查仪表盘等。当需要启动汽车时,只需调用car.start()方法即可,而无需在每个需要启动汽车的地方都编写相同的启动代码。
方法的重载
- 定义:在同一个类中,可以定义多个同名的方法,但这些方法的参数列表必须不同(参数的个数、类型或顺序不同),这就是方法的重载。
- 作用:方法重载使得在一个类中可以使用相同的方法名来实现不同的功能,根据传递的参数不同来调用不同的方法实现,提高了代码的可读性和灵活性。例如,在一个
Calculator类中,可以定义多个add方法来实现不同类型数据的加法运算,如add(int num1, int num2)用于两个整数相加,add(double num1, double num2)用于两个浮点数相加,add(int num1, int num2, int num3)用于三个整数相加。通过方法重载,在调用add方法时,编译器会根据传递的参数类型和个数来确定调用哪个具体的add方法,方便了程序员对不同类型数据的加法操作。
封装-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是可变字符串类,它允许对字符串进行修改,而不会创建新的对象。可以通过append、insert、delete等方法对字符串进行动态操作。例如,使用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;
}
}