JAVA面向对象程序设计1-6章总结
202402150401
第一章
1.1 JAVA概述
1.1.1 JAVA语言的特点
-
跨平台性:Java的一个核心特性是“一次编写,到处运行”(Write Once, Run Anywhere),通过Java虚拟机(JVM)实现。
-
面向对象:Java是一种面向对象的语言,支持封装、继承和多态性。
-
健壮性:Java的设计目标之一是减少错误,它提供了强类型检查和异常处理机制。
-
安全性:Java提供了一个安全的环境,用于执行代码,防止恶意代码的执行。
-
多线程:Java内置了对多线程的支持,使得开发多线程应用程序更加容易。
-
动态性:Java支持动态链接,这意味着在运行时可以动态地加载和链接用户自定义的类和库。
-
高性能:尽管Java最初被认为是解释型语言,但现代的JVM和即时编译器(JIT)技术使得Java应用程序可以接近或达到本地代码的性能。
-
分布式:Java提供了丰富的API来支持网络通信和分布式计算。
-
简单性:Java的设计去除了C++中的一些复杂特性,如操作符重载和多继承,使得语言更加简洁。
-
可移植性:Java代码可以在多种操作系统和平台上运行,无需修改。
-
解释型:Java代码在JVM上运行时会被解释执行,这使得它在不同的平台上具有很好的兼容性。
-
高性能垃圾回收:Java提供了自动内存管理和垃圾回收机制,减轻了程序员的内存管理负担。
-
广泛的社区和生态系统:Java有着庞大的开发者社区和丰富的开源库,这使得开发者可以快速找到解决方案和工具。
-
健壮的IDE和工具支持:Java有着强大的集成开发环境(IDE)和各种开发工具,如Eclipse、IntelliJ IDEA等,这些工具支持高效的开发流程。
-
持续更新:Java不断更新和改进,引入新特性和改进性能,以适应现代软件开发的需求。
1.1.2 JAVA跨平台原理
Java跨平台原理是基于Java虚拟机(Java Virtual Machine,JVM)实现的。Java程序在运行之前会被编译成字节码(Bytecode),这是一种与平台无关的中间代码。JVM是Java跨平台的核心组件,它负责解释执行这些字节码,并确保在不同操作系统和硬件平台上实现一致的行为。
以下是Java跨平台原理的关键组成部分:
-
字节码(Bytecode):Java源代码被编译成字节码,这是一种与平台无关的中间表示形式。字节码可以在任何支持JVM的设备上运行。
-
Java虚拟机(JVM):JVM是Java跨平台的关键实现。它负责加载字节码,解释执行字节码,并将字节码转换为特定操作系统和硬件平台上的机器代码。这样,Java程序可以在不同的平台上运行,而无需为每个平台重新编译。
-
即时编译(JIT):为了提高性能,JVM通常使用即时编译技术将字节码动态地编译成本地机器代码。这使得Java程序在运行时可以接近本地程序的性能。
-
类加载器(Class Loader):JVM中的类加载器负责加载字节码文件到内存中,并将其转换为JVM可以识别的对象。类加载器还负责确保类的唯一性和安全性。
-
垃圾回收(Garbage Collection):JVM中的垃圾回收器负责自动回收不再使用的对象,从而释放内存资源。这有助于防止内存泄漏和其他内存相关问题。
1.2 面向对象程序设计思想
1.2.1面向过程程序设计与面向对象程序设计的区别
面向过程程序设计是一种程序设计范式,强调程序的过程和步骤。程序被分解为一系列的步骤,每个步骤包含一系列的操作,通过依次执行这些步骤来完成任务。面向过程程序设计关注的是数据和算法的处理。
面向对象程序设计是一种程序设计范式,强调程序的对象和交互。程序被建模为一组对象,每个对象具有自己的状态和行为,并且可以相互交互。面向对象程序设计关注的是对象之间的关系和交互。
它们的区别如下:
- 程序的组织方式不同:面向过程程序设计以过程为中心,将问题分解为一系列的步骤和操作;而面向对象程序设计以对象为中心,将问题分解为一组相互关联的对象。
- 代码的复用性不同:面向过程程序设计侧重于代码的重复使用,通过函数或过程来封装可重复使用的代码;而面向对象程序设计侧重于对象的复用,通过继承和组合来复用已有的对象和类。
- 程序的扩展性不同:面向过程程序设计难以扩展和维护,因为程序是线性的,修改一个步骤可能会影响其他步骤;而面向对象程序设计具有更好的扩展性和维护性,因为对象之间的关系可以灵活地调整和修改。
- 编程思维方式不同:面向过程程序设计更偏向于顺序化的思维,强调算法和流程;而面向对象程序设计更偏向于抽象化的思维,强调问题的建模和对象之间的交互。
1.3 JAVA开发环境搭建
1.3.1 JDK与JRE
-
JDK(Java Development Kit)是Java开发工具包,它提供了开发Java应用程序所需要的工具和资源,包括编译器、调试器、运行时环境和其他与开发Java应用相关的工具。
-
JRE(Java Runtime Environment)是Java运行时环境,它包含Java虚拟机(JVM)和Java类库,用于运行已经编译完成的Java程序。
1.3.2 JDK安装
-
打开Oracle官方网站(https://www.oracle.com/java/technologies/javase-jdk11-downloads.html)。
-
在下载页面中,接受许可协议并选择适合你操作系统的安装包。例如,如果你使用的是Windows 64位操作系统,你可以选择Windows x64安装包。
-
点击“下载”按钮,开始下载JDK安装文件。
-
下载完成后,双击安装文件,启动安装向导。
-
在安装向导中,按照默认选项进行安装,或者根据个人需求选择自定义安装选项。
-
在安装完成后,点击“完成”按钮,完成安装过程。
完成以上步骤后,你已经成功安装了JDK。接下来,我们可以配置一些环境变量,以便在命令行中使用Java和Javac命令。
1.3.3 环境变量配置
-
打开控制面板,并进入“系统和安全”–>“系统”。
-
在系统窗口中,点击“高级系统设置”。
-
在系统属性窗口中,点击“环境变量”按钮。
-
在环境变量窗口中,找到“系统变量”区域,点击“新建”按钮。
-
在新建系统变量窗口中,输入变量名“JAVA_HOME”,并将变量值设置为JDK的安装路径(例如:C:\Program
Files\Java\jdk-11.0.7)。 -
在系统变量区域中,找到名为“Path”的变量,并点击“编辑”按钮。
-
在编辑环境变量窗口中,点击“新建”按钮,并输入“%JAVA_HOME%\bin”。
-
点击“确定”按钮,保存所做的更改。
1.4第一个Java程序:HelloWorld!
public class Helloworld{ //声明类名,类名必须与文件名一致
public static void main(String[] args){ //main()方法
System.out.println("HelloWorld!"); //输出一段文本,文本内容为HelloWorld!
}
}
1.5 Java常用开发工具
-
Eclipse:Eclipse是一个开放源代码的集成开发环境 (IDE),主要用于Java开发。它提供了丰富的功能和插件,让开发者可以轻松地编写、调试和测试Java程序。Eclipse安装与配置教程:https://www.bilibili.com/video/BV18E41177zQ/?share_source=copy_web
-
IntelliJ IDEA:IntelliJ IDEA是一款功能强大的Java集成开发环境,提供了智能代码完成、代码检查、重构等功能,可以大大提高开发效率。IntelliJ IDEA安装与配置教程:
https://www.bilibili.com/video/BV1FJ4He9EDX/?share_source=copy_web
第2章 Java编程基础
2.1 变量和常量
2.1.1 变量概念
变量是在程序中存储和表示数据的符号,可以改变其值的量。
2.1.2 常量的概念
常量是在程序中存储和表示数据的符号,其值在初始化后不能改变。
2.2 数据类型
2.2.1 基本数据类型,引用数据类型
基本数据类型是存储简单数据值的类型,引用数据类型是存储复杂对象的类型。
2.3 运算符与表达式
2.3.1 运算符
运算符是一种用于执行特定操作的符号。常见的运算符包括算术运算符、关系运算符、逻辑运算符、赋值运算符、位运算符等。
-
算术运算符用于执行基本的数值运算,包括加法(+)、减法(-)、乘法(*)、除法(/)、取模(%)、取余(%)等。
-
关系运算符用于比较两个表达式的关系,包括大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(==)、不等于(!=)等。
-
逻辑运算符用于组合或改变表达式的逻辑值,包括与(&&)、或(||)、非(!)等。
-
赋值运算符用于将一个值赋给变量,包括等于(=)、加等于(+=)、减等于(-=)、乘等于(*=)、除等于(/=)等。
-
位运算符是一种特殊的运算符,用于在二进制数的位级上进行操作。常见的位运算符包括与(&)、或(|)、异或(^)、取反(~)和移位(<<、>>)。
2.3.2 表达式与语句
2.4 条件结构,循环结构,跳转结构
2.4.1 条件语句
条件结构是编程中常用的一种结构,根据判断条件的真假来决定程序的执行路径。通过使用if、else、switch等关键字,可以根据不同的条件执行不同的代码块,从而实现不同的功能。
2.4.2 循环语句:for、while、do-while
-
for循环:通过指定循环变量的初始值、循环条件以及每次循环结束后的操作来控制循环的执行次数。
-
while循环:通过判断循环条件的真假来决定是否执行循环体,如果条件为真,则执行循环体,执行完后再判断条件,直到条件为假才结束循环。
-
do-while循环:先执行一次循环体,再判断循环条件的真假,如果条件为真,则继续执行循环体,每次循环结束后再次判断条件,直到条件为假才结束循环。
for循环常用于已知循环次数的情况,能够在循环语句中直接定义循环变量。
while循环适用于不确定循环次数的情况,循环条件可以是任意的表达式。
do-while循环与while循环类似,但是至少会执行一次循环体,适用于需要至少执行一次循环的情况。
2.4.3 跳转语句:break、continue
-
break语句用于立即终止当前循环或开关语句块的执行,并跳出该语句块。在循环中使用break,可以提前结束循环并继续执行循环外的代码。
-
continue语句用于中断本次循环的执行,并跳过剩下的代码,进入下一次循环。在循环中使用continue,可以跳过某些特定的迭代,继续执行下一次迭代。
2.5 方法
2.5.1方法的概念
方法是一种封装了特定功能的代码块,它允许将代码组织成可重用的单元。每个方法都有一个名称,可以接收输入参数,并返回结果。方法的调用可以执行特定任务,如计算、数据处理等。通过定义方法,代码更加模块化,易于维护和重用。
2.5.2 无参数方法、带参数方法、带返回值方法以及方法重载
无参数方法:无参数方法是指在方法的定义和调用过程中不需要传递任何参数的方法。例如:
public void sayHello() {
System.out.println("Hello!");
}
带参数方法:带参数方法是指在方法的定义和调用过程中需要传递参数的方法。例如:
public void printSum(int a, int b) {
int sum = a + b;
System.out.println("Sum is " + sum);
}
带返回值方法:带返回值方法是指在方法的定义和调用过程中可以返回一个值给调用者的方法。例如:
public int getSum(int a, int b) {
return a + b;
}
方法重载:方法重载是指在同一个类中可以有多个方法名相同但参数列表不同的方法。方法重载的目的是为了提高代码的复用性和灵活性。例如:
public int getSum(int a, int b) {
return a + b;
}
public double getSum(double a, double b) {
return a + b;
}
2.5.3 方法递归
递归是指在函数的实现过程中调用了自身函数的一种编程技巧。下面是几个常见的递归程序的例子,用于计算100以内的一些数学运算:
- 阶乘(factorial):计算一个非负整数n的阶乘,记作n!,定义为n! = n * (n-1)!,且0! = 1。
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
- 斐波那契数列(Fibonacci):计算斐波那契数列的第n个数,定义为F(n) = F(n-1) + F(n-2),其中F(0) = 0,F(1) = 1。
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)
- 累加求和(sum):计算从1到n的所有整数的和,定义为sum(n) = n + sum(n-1),其中sum(1) = 1。
def sum(n):
if n == 1:
return 1
else:
return n + sum(n-1)
这些递归程序都可以通过调用自身函数来实现,边界条件用于终止递归。在实际编程中,递归的使用需要注意控制递归的深度,以避免出现堆栈溢出的情况。
2.5.4 数组
-
数组的定义与声明
数组是一种容器对象,可以存储固定大小的同一类型元素。
数组的声明格式为:数据类型[] 数组名 = new 数据类型[元素个数];。 -
数组的创建与初始化
静态初始化:在声明数组的同时,使用花括号{}指定每个元素的值。
动态初始化:声明数组时,不指定元素个数,由JVM在运行时根据需要分配空间。 -
数组的访问
通过数组名和索引访问数组元素,索引从0开始。
数组名[索引]用于读取或修改数组中的元素。 -
数组的长度
每个数组都有一个length属性,表示数组中元素的数量。
数组名.length用于获取数组的长度。 -
数组的遍历
使用for循环或增强for循环(foreach循环)遍历数组。
-
多维数组
多维数组可以看作是数组的数组,如二维数组可以看作是数组的数组。
声明格式为:数据类型[][] 数组名 = new 数据类型[行数][];。 -
数组的复制
使用System.arraycopy方法或数组的clone方法复制数组。
注意clone方法复制的是数组的引用,而不是数组元素的深拷贝。 -
数组的排序
使用Arrays.sort()方法对数组进行排序。
可以对基本数据类型的数组和对象数组进行排序。 -
数组的搜索
使用Arrays.binarySearch()方法对已排序的数组进行二分查找。
-
数组的实用方法
Arrays.equals():比较两个数组是否相等。
Arrays.fill():用指定的值填充数组。
Arrays.copyOf():复制数组的一部分或全部。 -
异常处理
数组访问越界会引发ArrayIndexOutOfBoundsException。
需要合理处理数组操作中的异常,以避免程序崩溃。 -
数组作为方法参数
数组可以作为参数传递给方法,方法内部对数组的修改会影响到原数组。
第3章 面向对象程序设计(基础)
3.1 面向对象概念
3.1.1 面向对象的基本概念
面向对象是一种程序设计的思想,它将程序中的数据和操作数据的方法组织在一起,封装成对象。
封装、继承和多态是面向对象编程的三大特性。
-
封装是指将数据和方法封装在一个类中,通过访问修饰符来控制对数据的访问权限,提高了代码的可维护性、安全性和复用性。
-
继承是指一个类可以继承另一个类的属性和方法,子类可以在此基础上添加或修改自己的特性,实现了代码的重用、组织和扩展。
-
多态是指一个对象可以以多种形态呈现,根据实际的对象类型来执行不同的行为,提高了代码的灵活性、可扩展性和可维护性。
3.2 面向对象编程
3.2.1 类的定义与实例化
类的定义是指通过使用class关键字定义一个新的类。类是面向对象编程的基本概念,它是一种抽象的模板,用来描述具有相同属性和方法的对象集合。
类的实例化是指根据类来创建一个实际的对象。当一个类被实例化时,将会创建一个该类的对象。通过实例化一个类,可以使用类中定义的属性和方法。
3.2.2 对象的创建与使用
对象的创建和使用是通过类的实例化来实现的。首先,通过关键字new创建一个对象,并调用类的构造方法进行初始化。然后,可以使用对象的属性和方法进行操作。
例如,如果有一个名为Person的类,其中有属性name和age,以及方法getName()和getAge()用于获取属性的值。可以通过以下步骤来创建和使用对象:
// 定义一个类
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
}
// 创建对象并使用
Person person = new Person("Tom", 25);
System.out.println(person.getName()); // 输出: Tom
System.out.println(person.getAge()); // 输出: 25
3.2.3 成员变量默认值
成员变量的默认值取决于其数据类型。
- 数值类型(byte、short、int、long、float、double):0
- char类型:‘\u0000’ (空字符)
- boolean类型:false
- 引用类型(类、接口、数组):null
3.3 构造方法
3.3.1 什么是构造方法(包含无参和有参)
构造方法是用于创建和初始化对象的特殊方法。它的名称与类名相同,没有返回类型。构造方法可以分为无参构造方法和有参构造方法。
无参构造方法是没有参数的构造方法,用于给对象设置默认值。当一个类没有显式定义构造方法时,系统会自动为该类生成一个无参构造方法。
有参构造方法是带有参数的构造方法,用于根据传入的参数值来初始化对象的属性。通过不同的参数组合,可以创建不同状态的对象。
构造方法的作用是在创建对象时进行初始化操作,确保对象被正确地初始化。通过构造方法,可以为对象设置初始状态、分配内存等。构造方法使对象的创建更加灵活和可控。
3.3.2 构造方法的使用
构造方法是一个特殊的方法,用于创建对象时进行初始化操作。它的特点包括:
- 构造方法的名称必须与类名相同。
- 构造方法没有返回值类型,也没有返回值。
- 构造方法可以有参数,用于接收创建对象时传入的参数。
- 如果没有定义构造方法,编译器会自动生成一个无参的默认构造方法。
- 如果定义了有参数的构造方法,编译器不会生成默认构造方法。
使用构造方法的步骤如下:
- 在类中定义构造方法。可以是无参构造方法,也可以是有参数构造方法。
- 在创建对象时,使用new关键字调用构造方法进行初始化。
示例代码如下:
public class Person {
private String name;
private int age;
// 无参构造方法
public Person() {
System.out.println("无参构造方法被调用");
}
// 有参构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("有参构造方法被调用");
}
public static void main(String[] args) {
// 创建对象时调用无参构造方法进行初始化
Person p1 = new Person();
// 创建对象时调用有参构造方法进行初始化
Person p2 = new Person("张三", 18);
}
}
3.3.3 构造方法的重载
构造方法的重载是指在一个类中定义多个具有不同参数列表的构造方法。构造方法的重载可以用于初始化对象的不同属性或者提供多种对象的创建方式。
构造方法的重载可以通过以下方式实现:
- 改变构造方法的参数数量:可以定义多个构造方法,每个构造方法具有不同的参数数量。例如:
public class Person {
private String name;
private int age;
public Person() {
// 默认构造方法
}
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
此时可以通过new Person()、new Person(“Tom”)、new Person(“Tom”, 20)等不同方式创建Person对象。
- 改变构造方法的参数类型:可以定义多个构造方法,每个构造方法具有不同的参数类型。例如:
public class Point {
private int x;
private int y;
public Point() {
// 默认构造方法
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public Point(double x, double y) {
this.x = (int) x;
this.y = (int) y;
}
}
3.4 this关键字
this关键字就是在成员方法或者构造方法中使用,用来调用当前对象的成员变量、成员方法或构造方法,它代表当前对象。
this关键字的使用:
public class Person {
private String name;
public void setName(String name) {
this.name = name;
}
}
3.5 static关键字
3.5.1 静态变量
静态变量是在类级别定义的变量,不属于任何对象实例,而是被类的所有实例共享。它在程序运行期间只被初始化一次,生命周期与程序相同。当想调用静态变量时,使用类名.变量名进行调用。
public class MyClass {
// 静态变量在类中声明
public static int staticVariable = 10;
public static void main(String[] args){
// 通过类名访问静态变量
System.out.println("静态变量的值为: " + MyClass.staticVariable);
// 修改静态变量的值
MyClass.staticVariable = 20;
// 通过类名再次访问静态变量
System.out.println("修改后的静态变量的值为: " + MyClass.staticVariable);
}
}
3.5.2 静态方法
静态方法是与类相关联的方法,不需要创建类的实例即可调用。它使用类名直接访问,不能访问类的非静态成员变量和方法,因为它不依赖于类的任何特定对象。静态方法常用于工具类,提供与对象状态无关的功能。
静态方法是在类中声明的方法,可以直接通过类名调用,而无需创建类的实例。以下是一个包含静态方法的示例代码:
public class MyClass {
// 静态方法
public static void staticMethod() {
System.out.println("这是一个静态方法");
}
public static void main(String[] args) {
// 直接通过类名调用静态方法
MyClass.staticMethod();
}
}
3.5.3 静态代码块
静态代码块是在类加载阶段执行的一段代码,它在类被加载时只会执行一次。静态代码块主要用来进行类的初始化操作,比如初始化静态变量或执行静态方法等。静态代码块使用静态关键字static来修饰,在类的声明中,静态代码块位于类变量和构造函数之间。
public class Example {
private static int count;
static {
// 静态代码块中的初始化操作
count = 10;
System.out.println("静态代码块被执行");
}
public static void main(String[] args) {
System.out.println("count = " + count);
}
}
3.6 包
3.6.1 包的概念和使用
包(Package)是Java中组织类和接口的一种方式,用于管理复杂的项目结构。它帮助将功能相关的类和接口分组,便于维护和重用。使用包可以避免类名冲突,并通过访问控制修饰符(public, private等)保护类成员。创建包时,需要在源文件顶部声明package语句,其后跟包名,通常采用全小写,用点分隔符代替目录层次。编译后的类文件会存放在与包结构相对应的目录中。导入其他包中的类时,使用import语句。包的使用提高了代码的模块化和可读性。
// 文件名: Main.java
// 导入java.util包中的Scanner类
import java.util.Scanner;
// 自定义的包
package com.example.myapp;
// 公开的类
public class Main {
// 私有的静态方法
private static void privateMethod() {
System.out.println("This is a private method.");
}
// 公开的静态方法
public static void publicMethod() {
System.out.println("This is a public method.");
}
// 主方法
public static void main(String[] args) {
// 创建Scanner对象
Scanner scanner = new Scanner(System.in);
// 调用公开的方法
publicMethod();
// 通过类名调用私有的方法
Main.privateMethod();
// 使用Scanner对象接收用户输入并输出
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.println("Hello, " + name + "!");
}
}
第4章 面向对象程序设计(进阶版)
4.1 封装
4.1.1 访问修饰符
访问修饰符是用来定义一个类的成员(属性、方法等)可以被哪些其他类或代码访问的关键字。在Java语言中,有四种访问修饰符:
- public:公共的,可以被任何类访问。
- protected:受保护的,可以被同一个包内的类以及不同包中的子类访问。
- default(没有关键字修饰):默认的,可以被同一个包内的类访问。
- private:私有的,只能在当前类内部访问。
这些访问修饰符可以用于类的成员(属性、方法等),以控制其访问权限。通过合理地使用这些修饰符,可以使得代码更加安全、可维护和可扩展。
4.1.2 get()/set()方法
get()和set()方法是Java中常用的访问器(Accessor)和修改器(Mutator)方法。get()用于获取私有属性的值,而set()用于设置属性值。它们封装了对象的状态,允许外部代码通过这些方法安全地访问和修改对象属性,同时可以在方法内部添加逻辑来验证数据或执行其他操作。
以下是一个使用get()和set()方法的简单示例代码:
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person();
person.setName("John");
System.out.println(person.getName()); // 输出 "John"
}
}
4.2 继承
4.2.1 继承的概念
继承是一种面向对象的概念,允许一个类(子类)继承另一个类(父类)的属性和方法。子类可以重用父类的代码,实现代码复用,同时可以扩展或修改继承来的行为。Java只支持单继承,即一个类只能继承一个父类,但可以被多个类继承。继承通过关键字extends实现,子类继承父类后,可以访问父类的非私有属性和方法。子类还可以通过重写(Override)父类的方法来提供特定的实现。继承促进了代码的可维护性和可扩展性。
4.2.2 方法重写
方法重写是指在子类中重新定义父类中已经存在的方法。重写方法的目的是为了实现子类特有的功能或者修改父类方法的实现方式。在重写一个方法时,子类必须遵循以下规则:
- 方法名与参数列表必须与父类方法一致。
- 访问修饰符可以扩大或者缩小,但不能更改为另一种修饰符。
- 抛出的异常类型可以是父类方法抛出异常的子类,或者不抛出异常。
- 重写的方法不能比父类方法具有更低的访问级别。
重写方法时应该注意以下几点:
- 子类方法的返回类型必须与父类方法的返回类型相同或为其子类。
- 子类方法不能使用比父类方法更严格的访问修饰符。
- 重写的方法应该使用@Override注解,这样可以确保我们重写的方法是有效的。
重写方法的例子如下:
class Parent {
public void print() {
System.out.println("Parent class");
}
}
class Child extends Parent {
@Override
public void print() {
System.out.println("Child class");
}
}
4.3 super关键字
super关键字是Java中的一个特殊关键字,用于调用父类的构造方法、成员方法和成员变量。使用super关键字可以在子类中访问父类中被隐藏的成员变量或成员方法,避免了重名的问题。
父类构造方法的调用: 在子类的构造方法中,通过使用super关键字来调用父类的构造方法。这样可以先执行父类的构造方法,然后再执行子类的构造方法。
父类成员方法和成员变量的调用: 在子类中,如果想要访问父类中被子类隐藏的成员方法或成员变量,可以使用super关键字。
示例代码:
class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating.");
}
}
class Dog extends Animal {
String breed;
public Dog(String name, String breed) {
super(name);
this.breed = breed;
}
public void displayInfo() {
super.eat();
System.out.println("Breed: " + breed);
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Tom", "Labrador");
dog.displayInfo();
}
}
4.4 final关键字
"final"是一个关键字,用于修饰类、方法和变量。
-
当用final修饰类时,该类不能被继承,即为最终类。
-
当用final修饰方法时,该方法不能被子类重写,即为最终方法。
-
当用final修饰变量时,该变量为常量,即不可更改。
例如:
final class MyClass { // MyClass为最终类,不能被继承
final int x = 10; // x为常量,不可更改
final void myMethod() { // myMethod为最终方法,不能被重写
// 方法体
}
}
4.5 Object类
Object类是所有类的父类,也就是说所有的类都直接或间接地继承自Object类。Object类中定义了一些通用的方法,这些方法可以在任何类的对象上调用。
Object类中的常用方法有:
- equals():用于判断两个对象是否相等。
- hashCode():返回对象的哈希码值。
- toString():返回对象的字符串表示。
- getClass():返回对象所属的类。
- wait()、notify()和notifyAll():用于线程间的等待和通知。
- clone():创建并返回对象的一个拷贝。
- finalize():在对象被垃圾回收器回收之前调用。
4.6 多态
4.6.1 多态的概念
多态是面向对象编程的核心特性之一,指的是同一个方法调用,根据发送对象的不同,可以有不同的实现。在Java中,多态主要通过继承和接口实现,允许子类重写父类的方法,或者实现接口的方法。这样,同一个方法名可以对应多个不同的行为,具体执行哪个行为取决于对象的实际类型。多态提高了代码的灵活性和可扩展性,使得同一个接口可以被不同的对象以不同的方式实现。
以下是一个示例代码,实现了多态的概念:
// 父类 Animal
class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
// 子类 Dog
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("狗发出汪汪的声音");
}
}
// 子类 Cat
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("猫发出喵喵的声音");
}
}
public class PolymorphismExample {
public static void main(String[] args) {
Animal animal1 = new Dog(); // 父类类型的引用变量引用子类对象
animal1.makeSound(); // 调用子类中重写的方法
Animal animal2 = new Cat(); // 父类类型的引用变量引用另一个子类对象
animal2.makeSound(); // 调用另一个子类中重写的方法
}
}
4.6.2 引用类型数据转换
在多态中,引用类型数据转换是指将一个子类的对象赋值给其父类的引用变量,或者将一个父类的引用变量转换成其子类的引用变量。这种转换可以在编译时或运行时进行。
- 向上转型(Upcasting):将子类对象赋值给父类引用变量。这种转换是安全的,因为子类对象继承了父类的属性和方法。通过父类引用变量,可以调用子类和父类共有的方法,但不能访问子类特有的方法。
Animal animal = new Cat();
animal.speak(); // 调用的是子类的方法
- 向下转型(Downcasting):将父类引用变量转换成子类的引用变量。这种转换可能不安全,需要进行类型检查和类型转换。只有在确定父类引用变量引用的对象是子类对象时,才能进行向下转型。
Animal animal = new Cat();
if (animal instanceof Cat) {
Cat cat = (Cat) animal; // 进行类型转换
cat.play(); // 访问子类特有的方法
}
- instanceof运算符:用于检查一个对象是否是某个类的实例。它返回一个布尔值,如果对象是指定类的实例或其子类的实例,则返回true;否则返回false。
Animal animal = new Cat();
if (animal instanceof Cat) {
// 对象是Cat类或其子类的实例
} else if (animal instanceof Dog) {
// 对象是Dog类或其子类的实例
} else {
// 对象不是Cat类或Dog类的实例
}
4.7 抽象类
抽象类是Java中不能被实例化的类,用于定义一个通用模板,包含抽象方法,这些方法只有声明没有实现。它允许子类继承并实现这些抽象方法,从而提供具体的功能。抽象类通过关键字abstract定义,可以包含构造方法、属性和具体方法,但不能直接实例化。
// 定义抽象类
abstract class Animal {
// 抽象方法
public abstract void sound();
}
// 定义具体子类
class Dog extends Animal {
// 实现抽象方法
public void sound() {
System.out.println("The dog barks");
}
}
class Cat extends Animal {
public void sound() {
System.out.println("The cat meows");
}
}
public class Main {
public static void main(String[] args) {
// 创建对象
Animal dog = new Dog();
Animal cat = new Cat();
// 调用方法
dog.sound();
cat.sound();
}
}
4.8 接口
接口(Interface)定义了一组方法规范,但不提供实现。它使用interface关键字声明,可以包含常量、抽象方法和默认方法。接口旨在实现多继承,允许一个类实现多个接口,从而拥有多个行为集合。接口主要用于定义类的行为蓝图,确保实现类遵循特定的方法签名,增强代码的模块化和灵活性。
// 定义接口
interface Animal {
void sound();
void move();
}
// 实现接口
class Dog implements Animal {
@Override
public void sound() {
System.out.println("The dog barks");
}
@Override
public void move() {
System.out.println("The dog runs");
}
}
class Cat implements Animal {
@Override
public void sound() {
System.out.println("The cat meows");
}
@Override
public void move() {
System.out.println("The cat jumps");
}
}
public class Main {
public static void main(String[] args) {
// 创建对象
Animal dog = new Dog();
Animal cat = new Cat();
// 调用方法
dog.sound();
dog.move();
cat.sound();
cat.move();
}
}
第5章 异常
5.1 异常的概念、体系和类型
异常是用于处理程序运行时错误的一种机制。它允许程序在遇到错误时,不直接崩溃,而是提供一种控制错误的方式。异常体系基于类Throwable,分为两大类:错误(Error)和异常(Exception)。错误通常是JVM内部问题,如OutOfMemoryError,不可恢复;异常则分为可检查(Checked)和非检查(Unchecked)异常。可检查异常需要在编译时处理,如IOException;非检查异常是程序运行时错误,如NullPointerException,不需要显式声明。正确处理异常可以提高程序的健壮性和用户体验。
5.2 异常处理
5.2.1 try、catch、finally、throw和throws五大关键字的用法
try、catch、finally、throw和throws是Java中用于处理异常的关键字。
- try-catch语句用于捕获和处理异常。try块中放置可能会抛出异常的代码,而catch块用于处理捕获到的异常。
示例代码:
try {
// 可能会抛出异常的代码
int result = 10 / 0; // 除以0会抛出ArithmeticException异常
} catch (ArithmeticException e) {
// 处理捕获到的异常
System.out.println("除数不能为零");
}
- finally语句块用于在try-catch语句结束之后执行。无论是否发生异常,finally语句块中的代码总是会被执行。
示例代码:
try {
// 可能会抛出异常的代码
int result = 10 / 0; // 除以0会抛出ArithmeticException异常
} catch (ArithmeticException e) {
// 处理捕获到的异常
System.out.println("除数不能为零");
} finally {
// 无论是否发生异常,该语句块中的代码都会被执行
System.out.println("finally语句块");
}
- throw关键字用于手动抛出异常。可以使用throw关键字抛出任意类型的异常。
示例代码:
public void checkNumber(int number) throws MyException {
if (number < 0) {
throw new MyException("输入的数字不能为负数");
}
}
- throws关键字用于声明方法可能抛出的异常。在方法的声明中使用throws关键字,表示该方法可能会抛出指定类型的异常,由调用该方法的地方来处理。
示例代码:
public void readFile() throws FileNotFoundException {
// 读取文件的代码
File file = new File("test.txt");
FileInputStream fileInputStream = new FileInputStream(file);
}
这是对五个关键字的简单说明,它们在Java中的异常处理中起到了重要的作用。
第6章 接口的定义和实现
6.1 包装类
6.1.1 基本数据类型和包装类
Integer类是Java中用来表示整数的包装类,提供了许多方法来操作整数值。下面是Integer类中的一些主要方法及示例代码:
- intValue():
Integer num = 10;
int value = num.intValue(); // 将Integer对象转换为int类型的值
System.out.println(value); // 输出:10
- toString():
Integer num = 10;
String str = num.toString(); // 将Integer对象转换为字符串表示
System.out.println(str); // 输出:"10"
- parseInt(String s):
String str = "123";
int value = Integer.parseInt(str); // 将字符串解析为整数
System.out.println(value); // 输出:123
- valueOf(int i):
int value = 10;
Integer num = Integer.valueOf(value); // 返回一个指定整数值的Integer对象
System.out.println(num); // 输出:10
- compareTo(Integer anotherInteger):
Integer num1 = 10;
Integer num2 = 5;
int result = num1.compareTo(num2); // 比较两个Integer对象的值
System.out.println(result); // 输出:1,因为num1大于num2
- equals(Object obj):
Integer num1 = 10;
Integer num2 = 10;
boolean isEqual = num1.equals(num2); // 比较两个Integer对象是否相等
System.out.println(isEqual); // 输出:true
这些是Integer类中的一些常用方法,通过它们可以对整数进行转换、比较和操作等操作。
6.1.2 自动装箱和拆箱
自动装箱是将基本数据类型转换为对应的包装类对象的过程,而自动拆箱是将包装类对象转换为对应的基本数据类型的过程。
示例代码:
Integer integer = 10; // 自动装箱
int value = integer; // 自动拆箱
6.1.3 大数字运算
Java的包装类提供了大数字运算的能力,尤其是BigInteger和BigDecimal类,它们可以处理超出基本数据类型范围的大数字。
示例代码:
BigInteger bigInt = new BigInteger("12345678901234567890");
BigDecimal bigDec = new BigDecimal("12345678901234567890.123456789");
6.2 String类概述
6.2.1 String类
String类用于表示字符串,它是不可变的,即一旦创建,其值不能被改变。
示例代码:
String str = "Hello, World!";
6.2.2 String类查找方法
String类提供了多种查找方法,如indexOf、contains等。
示例代码:
String str = "Hello, World!";
int index = str.indexOf("World"); // 返回"World"的索引
6.2.3 String类转移方法
String类提供了转移方法,如toLowerCase、toUpperCase等。
示例代码:
String str = "Hello, World!";
String lower = str.toLowerCase(); // 转换为小写
6.2.4 String类中的其他方法
String类还提供了其他方法,如substring、replace等。
示例代码:
String str = "Hello, World!";
String sub = str.substring(7); // 返回"World!"
6.3 StringBuffer类和StringBuilder类
6.3.1 StringBuffer类
StringBuffer类用于可变的字符串操作,它是线程安全的。
示例代码:
StringBuffer sb = new StringBuffer("Hello");
sb.append(", World!");
6.3.2 StringBuffer类常见方法
StringBuffer类提供了append、insert、reverse等方法。
示例代码:
StringBuffer sb = new StringBuffer("Hello");
sb.insert(5, ", World!");
6.3.3 StringBuilder类
StringBuilder类用于可变的字符串操作,它不是线程安全的,性能更好。
示例代码:
StringBuilder sb = new StringBuilder("Hello");
sb.append(", World!");
6.3.4 链式编程
StringBuilder和StringBuffer都支持链式编程。
示例代码:
StringBuilder sb = new StringBuilder("Hello").append(", ").append("World!");
6.4 时间日期和相关类
6.4.1 时间戳
时间戳是自1970年1月1日00:00:00 GMT以来的毫秒数。
示例代码:
long timestamp = System.currentTimeMillis();
6.4.2 Date类
Date类用于表示特定的瞬间,精确到毫秒。
示例代码:
Date date = new Date();
6.4.3 SimpleDateFormat类
SimpleDateFormat类用于格式化和解析日期。
示例代码:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String formattedDate = sdf.format(new Date());
6.4.4 Calendar类
Calendar类是一个抽象类,提供了操作日期的方法。
示例代码:
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
6.5 其他类
6.5.1 Math类
Math类是Java中提供了一系列用于执行基本数学运算的工具类,如三角函数、指数、平方根等。
示例代码:
double result = Math.sqrt(16); // 返回4.0
double power = Math.pow(2, 3); // 返回8.0
double random = Math.random(); // 返回一个随机数
6.5.2 Random类
Random类用于生成一系列的随机数。它比Math.random()方法提供更多的随机数生成方法,如nextInt()、nextDouble()等。
示例代码:
Random random = new Random();
int nextInt = random.nextInt(100); // 返回一个0到99之间的随机整数
double nextDouble = random.nextDouble(); // 返回一个0.0到1.0之间的随机小数
6.5.3 UUID类
UUID(Universally Unique Identifier)类用于生成一个唯一的标识符。它遵循RFC 4122标准,生成的UUID几乎可以保证在空间和时间上的唯一性。
示例代码:
UUID uuid = UUID.randomUUID(); // 生成一个随机的UUID
String uuidString = uuid.toString(); // 将UUID转换为字符串形式
6.5.4 枚举类
枚举(Enum)是一种特殊的类,它定义了一个常量的集合。枚举类型的每个元素都是枚举类的一个实例。
示例代码:
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
public class TestEnum {
public static void main(String[] args) {
for (Day day : Day.values()) {
System.out.println(day);
}
}
}
在这个示例中,Day是一个枚举类型,它定义了一周的七天。Day.values()方法返回枚举类型的所有元素数组。枚举类可以有自己的方法和属性,使得它们比常量集合更加灵活。
1152

被折叠的 条评论
为什么被折叠?



