简介:Java是广泛应用于企业级应用开发的流行编程语言。这份笔记详细介绍了Java的基础知识,从环境配置到面向对象编程,再到异常处理、集合框架、IO流、多线程等高级主题。通过学习这些关键知识点,初学者能迅速入门Java编程,并为深入学习奠定基础。
1. Java语言简介
Java语言自1995年面世以来,一直是软件开发领域中最具影响力的语言之一。它是一种跨平台、面向对象的编程语言,广泛应用于企业级应用开发、移动应用、嵌入式系统等多个领域。Java的编程范式包括类和对象的继承、封装、多态等面向对象特性,而它的设计理念强调“一次编写,到处运行”,即Write Once, Run Anywhere(WORA)。Java语言的稳定性和强大的社区支持,使其成为众多开发者和企业的首选。本章将简要介绍Java语言的起源、特性以及其在现代编程语言中的地位。
2. Java环境配置与基本语法
Java作为最流行的编程语言之一,对开发环境的搭建有着严格的要求。本章将带领读者了解如何搭建一个适合进行Java开发的环境,并介绍Java的基础语法,为深入学习Java语言打下坚实的基础。
2.1 Java环境的搭建
2.1.1 JDK的安装与配置
Java Development Kit (JDK) 是进行Java开发的基础工具,包含编译器、运行时环境和一系列实用工具。JDK的安装对于后续所有Java开发至关重要。
- 下载JDK : 访问Oracle官方网站或其他JDK提供商,选择适合操作系统的JDK版本进行下载。截至知识更新点,Java 11为最新稳定版本,推荐下载此版本或更高版本。
- 安装JDK : 根据操作系统的不同,安装步骤会有所差异。对于Windows系统,双击下载的.exe文件,按照安装向导提示进行操作;对于Mac系统,可使用.dmg包进行安装;而Linux用户则需解压下载的压缩包,并设置相应的环境变量。
- 配置环境变量 : JDK安装完成后,需要配置JAVA_HOME环境变量以及更新PATH环境变量,使得系统能够识别java命令和javac命令。
示例代码 (Windows系统):
batch set JAVA_HOME=C:\Program Files\Java\jdk-11.0.1 set PATH=%JAVA_HOME%\bin;%PATH%
逻辑分析与参数说明 :上述代码设置JAVA_HOME环境变量为JDK安装路径,并将JDK的bin目录添加到PATH环境变量中,确保命令行工具的可执行路径。注意路径中的斜杠方向和空格处理,可能根据不同的操作系统而有所不同。
- 验证安装 : 打开命令行工具,输入
java -version
,若能显示JDK版本,则表示安装配置成功。
2.1.2 开发工具的选择与设置
在JDK安装配置完毕后,选择一款合适的集成开发环境(IDE)将极大提升开发效率。目前主流的Java开发工具有IntelliJ IDEA, Eclipse, NetBeans等。
- IntelliJ IDEA : 强调智能代码助手、代码自动补全及重构。它的社区版是开源免费的,而专业版则提供更多高级功能。
- Eclipse : 作为开源项目,Eclipse提供了丰富的插件支持,灵活性高,被很多开发者喜爱。
- NetBeans : Oracle官方支持的Java IDE,具有良好的模块化和扩展性。
选择好IDE后,需要配置Java编译器路径等环境选项,确保IDE使用的JDK版本与之前安装的JDK版本一致。
示例代码 (IntelliJ IDEA配置JDK): plaintext File -> Project Structure -> Project -> Project SDK
逻辑分析与参数说明 :在IntelliJ IDEA中,选择项目设置中的项目SDK配置项,点击“New…”按钮,然后选择“JDK”,选择JDK安装目录,完成JDK路径的配置。
2.2 Java基本语法
2.2.1 数据类型与变量
Java是一种强类型语言,这意味着每个变量都需要声明其类型。Java的数据类型分为基本数据类型和引用数据类型。
- 基本数据类型 : 包括整型(byte、short、int、long)、浮点型(float、double)、字符型(char)和布尔型(boolean)。
- 引用数据类型 : 包括类、接口、数组。
变量的声明语法为: 类型 变量名;
,例如:
int age = 20;
double salary = 10000.5;
boolean isEmployed = true;
2.2.2 运算符与表达式
Java提供了丰富的运算符,用于构建表达式。运算符主要分为算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符等。
- 算术运算符 : 包括加(+)、减(-)、乘(*)、除(/)、取模(%)等。
- 关系运算符 : 用于比较两个变量,包括大于(>)、小于(<)、等于(==)、不等于(!=)等。
- 逻辑运算符 : 包括逻辑与(&&)、逻辑或(||)、逻辑非(!)等。
表达式可以嵌套使用,但需要注意运算符的优先级和结合性。
2.2.3 控制流程(循环、条件判断)
Java中的控制流程主要通过条件判断和循环结构实现。
- 条件判断 :
if
,else if
,else
和switch
语句用于基于条件执行不同的代码块。 示例代码 (条件判断):java if (score >= 90) { System.out.println("优秀"); } else if (score >= 80) { System.out.println("良好"); } else { System.out.println("一般"); }
逻辑分析与参数说明 : 当 score
变量值大于或等于90时,输出"优秀";在50到89之间时输出"良好";小于50时输出"一般"。
- 循环结构 : 包括
for
、while
和do-while
三种循环。
示例代码 (循环结构): java for (int i = 0; i < 10; i++) { System.out.println("循环次数:" + i); }
逻辑分析与参数说明 : 此 for
循环会在循环变量 i
的值小于10时重复执行循环体,每次循环结束后, i
的值增加1。
通过本章节的介绍,我们已了解了如何在计算机上搭建Java环境,并学习了Java的基本语法,包括数据类型、运算符和控制流程。下一章节我们将深入探讨面向对象编程的基本概念,为读者展示Java面向对象的强大功能。
3. 类与对象的面向对象编程
面向对象编程(Object-Oriented Programming,简称OOP)是一种非常流行的编程范式,它以对象为基础,将数据(属性)和行为(方法)封装起来,形成具有独立功能的单元。在Java语言中,一切皆为对象,这使得面向对象的概念贯穿整个编程语言的核心。
3.1 面向对象基本概念
3.1.1 类与对象的定义
在Java中,类(Class)是创建对象的蓝图或模板,对象(Object)是类的实例。类中定义了对象的属性和方法,属性是对象的状态信息,方法则是对象的行为。
为了更好地理解类和对象的概念,我们可以从现实生活中的例子出发。例如,一个“汽车”类可能包含颜色(color)、品牌(brand)等属性,以及启动(start)、停止(stop)等方法。
下面是一个简单的汽车类定义:
public class Car {
// 属性
String color;
String brand;
// 方法
public void start() {
System.out.println("汽车启动了");
}
public void stop() {
System.out.println("汽车停止了");
}
}
要创建一个 Car
类的实例,我们可以这样做:
public class Main {
public static void main(String[] args) {
// 创建Car类的对象
Car myCar = new Car();
// 访问属性和方法
myCar.color = "红色";
myCar.brand = "宝马";
myCar.start();
myCar.stop();
}
}
3.1.2 类的继承与多态
继承(Inheritance)是面向对象编程中的一个核心概念,它允许一个类继承另一个类的特性。继承可以使得子类获得父类的属性和方法,还可以增加新的属性和方法或者重写(Override)父类的方法。
Java使用 extends
关键字来实现继承。例如,如果我们有一个 Vehicle
类,然后创建一个 Car
类继承自 Vehicle
,那么 Car
类就可以拥有 Vehicle
类的所有属性和方法。
class Vehicle {
void run() {
System.out.println("车在运行");
}
}
class Car extends Vehicle {
void run() {
System.out.println("汽车在运行");
}
}
class Main {
public static void main(String[] args) {
Car car = new Car();
car.run(); // 输出: 汽车在运行
}
}
多态(Polymorphism)是指允许不同类的对象对同一消息做出响应。Java多态的实现依赖于继承和接口。多态性可以分为编译时多态和运行时多态。编译时多态主要指方法重载,运行时多态则主要指方法重写。
3.2 面向对象高级特性
3.2.1 抽象类与接口
抽象类是不能实例化的类,它通常用于表示一个概念或基类,可以包含抽象方法和具体方法。抽象方法是只有声明没有具体实现的方法,具体子类必须提供实现。
接口(Interface)则是一种完全抽象的类,它允许声明没有方法体的方法。一个类可以通过 implements
关键字来实现一个或多个接口。
下面是一个抽象类和接口的简单示例:
// 抽象类示例
abstract class Animal {
abstract void sound();
}
// 实现接口示例
class Dog extends Animal implements Pet {
public void sound() {
System.out.println("汪汪");
}
public void play() {
System.out.println("狗在玩耍");
}
}
interface Pet {
void play();
}
3.2.2 内部类与匿名类
内部类是指在一个类的内部再定义一个类。它主要有两种类型:成员内部类和局部内部类。内部类的一个重要特性是它可以访问其所在类的私有属性和方法。
匿名类是一种没有名字的内部类,它可以用来实现一个接口或抽象类的部分或全部功能。
public interface HelloWorld {
void greet();
}
public class HelloWorldImpl implements HelloWorld {
public void greet() {
System.out.println("Hello, World!");
}
public static void main(String[] args) {
HelloWorld helloWorld = new HelloWorldImpl();
helloWorld.greet();
// 匿名类实现接口
HelloWorld anonymousHelloWorld = new HelloWorld() {
public void greet() {
System.out.println("Hello, anonymous World!");
}
};
anonymousHelloWorld.greet();
}
}
通过本章节的介绍,我们深入理解了面向对象编程中的基本概念,如类与对象的定义、继承、多态,以及类的高级特性,比如抽象类、接口、内部类以及匿名类的用法。在接下来的章节中,我们将继续探讨Java语言中封装、继承、多态的深入解析以及更多面向对象编程技术的高级应用。
4. ```
第四章:封装、继承、多态深入解析
4.1 封装的实现与意义
封装是面向对象编程的三大特性之一,它隐藏了对象的内部实现细节,并且规定了对象对外部的接口,提高了程序的安全性和封装性。本章节深入解析封装的概念,探讨如何通过访问修饰符和构造方法来实现封装,以及封装对于编程实践的意义。
4.1.1 访问修饰符的使用
在Java中,访问修饰符是控制类成员访问权限的关键元素。包括 public
、 protected
、 default
(无修饰符,也称为包访问权限)和 private
。不同访问修饰符允许访问的范围如下表所示:
| 访问修饰符 | 类内部 | 同一包内 | 子类 | 全局范围 | | --- | --- | --- | --- | --- | | public | 是 | 是 | 是 | 是 | | protected | 是 | 是 | 是 | 否 | | default | 是 | 是 | 否 | 否 | | private | 是 | 否 | 否 | 否 |
以一个简单的Java类为例,说明不同访问修饰符的使用:
public class Person {
private String name;
private int age;
protected String nationality;
String address;
public Person(String name, int age, String nationality, String address) {
this.name = name;
this.age = age;
this.nationality = nationality;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
// ... 其他方法 ...
}
在这个例子中, name
和 age
字段是私有的( private
),只有在 Person
类内部可以访问,外部访问必须通过公有( public
)的getter和setter方法进行。
4.1.2 构造方法与初始化块
构造方法用于创建对象时初始化对象的状态。在Java中,如果没有显示定义构造方法,编译器会默认提供一个无参构造方法。一旦定义了构造方法,编译器则不会提供默认无参构造方法。构造方法可以重载,以便于创建具有不同初始状态的对象。此外,初始化块(静态初始化块和实例初始化块)也可以用来初始化对象状态。
public class Vehicle {
private String make;
private String model;
private int year;
// 初始化块
{
year = 2020; // 默认赋值
}
// 构造方法
public Vehicle(String make, String model) {
this.make = make;
this.model = model;
}
// ... 其他方法 ...
}
在这个例子中,我们定义了一个 Vehicle
类,并提供了一个构造方法来初始化 make
和 model
字段。同时,使用了一个实例初始化块来设置默认的年份值。
封装的意义不仅在于隐藏实现细节,更重要的是提供了一种清晰定义类内部状态的手段。这有助于维持代码的可维护性和可扩展性。通过封装,类的内部实现可以在不影响外部代码的前提下进行更改,从而提高程序的健壮性。
4.2 继承与多态的应用
继承是面向对象编程中允许新创建的类(称为子类)获得一个或多个现有类(称为父类)的属性和方法的机制。多态则是允许不同类的对象对同一消息做出响应的能力。本节深入探讨Java中继承和多态的实现方式,包括方法重载与重写,以及 super
与 this
关键字的使用。
4.2.1 方法重载与重写
方法重载(Overloading)和方法重写(Overriding)是实现多态的两种主要手段。方法重载允许类中存在多个同名但参数不同的方法;方法重写则允许子类提供特定于自己的实现版本的方法。
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Dog barks");
}
public void makeSound(int times) {
for (int i = 0; i < times; i++) {
System.out.println("Dog barks");
}
}
}
// ...
Dog dog = new Dog();
dog.makeSound(); // 调用重写后的方法
dog.makeSound(3); // 调用重载后的方法
4.2.2 super与this关键字的使用
在Java中, super
关键字用于访问父类的属性、方法和构造方法; this
关键字则用于访问当前对象的属性和方法,或者引用当前对象。
class Parent {
int x = 100;
Parent() {
System.out.println("Parent constructor");
}
void show() {
System.out.println("Parent show()");
}
}
class Child extends Parent {
int x = 200;
Child() {
// 调用父类的构造方法
super();
System.out.println("Child constructor");
}
void display() {
// 访问父类的方法
super.show();
// 访问本类的实例变量x
System.out.println(this.x);
}
void show() {
// 调用本类的方法
System.out.println("Child show()");
}
}
// ...
Child child = new Child();
child.display(); // 输出父类的show()方法结果和子类的x值
child.show(); // 输出子类的show()方法结果
继承和多态为Java编程提供了灵活性和扩展性。通过继承,我们可以建立类之间关系,而多态则使得可以使用父类类型的引用来操作子类对象。这不仅减少了代码冗余,也使得程序更加易于扩展和维护。通过合理地使用 super
和 this
关键字,我们能够更精确地控制对象的行为和状态。
5. Java异常处理机制
异常处理是Java语言中一个非常重要的机制,它允许程序代码处理在运行时发生的各种异常事件,从而提高程序的健壮性和可靠性。异常是程序运行时发生的不正常情况,它会导致程序运行过程的中断。Java中的异常处理通过异常类的层次结构以及关键字来实现对异常的捕获和处理。
5.1 异常类的层次结构
Java语言中的异常可以分为两大类:可检查异常(checked exceptions)和非检查异常(unchecked exceptions)。这种分类是基于它们的继承关系,不同的异常类在类层次结构中扮演不同的角色。
5.1.1 可检查异常与非检查异常
可检查异常(checked exceptions)是指那些在编译时必须被处理的异常。这类异常是通过继承 java.lang.Exception
类但不继承 java.lang.RuntimeException
类来实现的。由于可检查异常是编译时异常,编译器会强制要求开发者对这些异常进行捕获处理,以确保程序的稳定性。典型的可检查异常包括 IOException
、 SQLException
等。
非检查异常(unchecked exceptions),也被称作运行时异常(runtime exceptions),是指那些不要求开发者显式处理的异常。这些异常是从 java.lang.RuntimeException
类或其子类派生出来的异常,如 NullPointerException
、 IndexOutOfBoundsException
、 IllegalArgumentException
等。这类异常通常是由程序员的错误导致的,如逻辑错误或者不当的操作。它们通常在运行时抛出。
5.1.2 自定义异常类
除了Java提供的标准异常类外,开发者也可以根据需求创建自己的异常类。自定义异常类一般需要继承自 Exception
类(对于可检查异常)或 RuntimeException
类(对于非检查异常)。自定义异常类通常用于封装特定的错误信息,使得在抛出异常时能够提供更多的上下文信息。
public class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}
在上述示例中, CustomException
类继承自 Exception
,定义了一个带消息参数的构造方法。在实际应用中,我们可以通过这种方式来创建更具体的异常类。
5.2 异常处理技巧
在Java中处理异常,开发者可以使用 try-catch-finally
语句块来捕获和处理异常。在特定代码块的外围使用 try
,在 try
块内部发生异常的地方使用 catch
来捕获和处理异常,而 finally
块包含无论是否发生异常都需要执行的代码。
5.2.1 try-catch-finally语句
try
块用于包围可能会抛出异常的代码, catch
块用于捕获并处理在 try
块中指定的类型的异常。 finally
块是可选的,它通常用于执行清理工作,如关闭文件流等操作。
try {
// 尝试执行的代码
} catch (SomeException e) {
// 处理特定异常
} catch (AnotherException e) {
// 处理其他类型异常
} finally {
// 清理资源的代码
}
在上述结构中, try
块中的代码首先执行,如果在执行过程中抛出了 SomeException
类型的异常,那么第一个 catch
块会被执行。如果 try
块中的代码抛出的异常类型不是 SomeException
,则会尝试与下一个 catch
块中指定的异常类型进行匹配。如果没有任何 catch
块匹配,则异常会被向上传递到调用栈。 finally
块无论是否捕获到异常都会执行。
5.2.2 异常链与异常抑制
异常链允许一个异常作为另一个异常的原因,并且允许捕获者获取前一个异常的详细信息。在Java中,可以使用 initCause()
方法来建立异常链,或者在构造异常时直接传递前一个异常作为构造参数。
异常抑制是一种避免显示多个相同异常的机制。在Java 7及以后的版本中,可以使用 Throwable
类中的 addSuppressed()
方法来添加抑制的异常,以及使用 getSuppressed()
方法来获取抑制的异常列表。
在实际的应用程序中,合理使用异常处理技巧可以提高代码的可读性和可维护性,同时能确保在异常情况下资源能够被正确释放。
通过本章节的介绍,您应该已经对Java异常处理机制有了深入的理解。异常类的层次结构提供了不同异常类型的基础,异常处理技巧则给出了如何在代码中灵活应用这些异常类的最佳实践。异常处理对于提高Java应用程序的稳定性和用户体验至关重要,因此开发者应当将本章的知识熟练运用于日常的开发工作中。
6. 字符串与数组操作
6.1 字符串的处理
6.1.1 String类的特点与不可变性
字符串在Java中是一个非常重要的数据类型,我们使用String类来创建和操作字符串。String对象一旦被创建,它的值就不能被改变。这意味着每次对String对象的修改都会生成一个新的String对象。
String的不可变性带来了以下几个优点:
- 安全性:由于String对象是不可变的,所以它是线程安全的,可以在多线程环境下共享。
- 哈希码的一致性:String对象一旦被创建,它的哈希码会被缓存。这意味着在应用中可以利用这一点进行性能优化,如存储字符串在HashMap中。
- 字符串常量池:Java为了提高性能和减少内存消耗,引入了字符串常量池的概念。当创建一个字符串常量时,JVM首先会检查池中是否有相同值的字符串对象,如果有,则返回池中的字符串对象;否则,创建新的字符串对象并将其添加到池中。
6.1.2 字符串构建与常用方法
字符串的构建和操作是Java编程中一项基础且重要的技能。我们经常使用new关键字来创建String对象,但实际上Java提供了更简洁的字符串字面量方式:
String str = "Hello, World!";
String类中定义了许多有用的方法,例如:
-
length()
: 返回字符串的长度。 -
charAt(int index)
: 返回指定索引处的字符。 -
substring(int beginIndex)
: 返回一个新字符串,它是此字符串的一个子字符串。 -
concat(String str)
: 将指定字符串连接到此字符串的结尾。 -
replace(char oldChar, char newChar)
: 返回一个新字符串,它是通过用newChar
替换此字符串中出现的所有oldChar
得来的。 -
trim()
: 返回字符串的副本,忽略前后空白。
代码示例
String originalString = " Hello, World! ";
String trimmedString = originalString.trim();
int length = trimmedString.length();
char firstChar = trimmedString.charAt(0);
String newString = trimmedString.replace(' ', '-');
System.out.println("原始字符串: " + originalString);
System.out.println("去空白字符串: " + trimmedString);
System.out.println("字符串长度: " + length);
System.out.println("第一个字符: " + firstChar);
System.out.println("替换空格后的字符串: " + newString);
在上述代码中,我们使用 trim()
方法去除了字符串两端的空白,然后用 length()
方法获取字符串长度,并用 charAt()
获取了第一个字符,最后用 replace()
方法替换了字符串中的空格字符。
6.2 数组的操作
6.2.1 数组的声明与初始化
数组是用于存储一系列相同类型数据的数据结构。在Java中,数组可以存储基本数据类型和引用数据类型。
声明数组
数组的声明有以下两种形式:
int[] intArray; // 方式一
int intArray[]; // 方式二
初始化数组
数组的初始化可以静态初始化或动态初始化:
// 静态初始化
int[] intArray = {1, 2, 3, 4, 5};
// 动态初始化
String[] stringArray = new String[5]; // 默认初始化为空字符串
6.2.2 数组的遍历与拷贝
遍历数组是常见的操作,可以通过for循环或者增强for循环来实现:
int[] numbers = {1, 2, 3, 4, 5};
// 使用for循环遍历数组
for (int i = 0; i < numbers.length; i++) {
System.out.println("数组元素: " + numbers[i]);
}
// 使用增强for循环遍历数组
for (int num : numbers) {
System.out.println("数组元素: " + num);
}
数组的拷贝可以通过 System.arraycopy()
方法实现,这个方法可以高效地将一个数组的部分或全部元素复制到另一个数组中:
int[] sourceArray = {1, 2, 3, 4, 5};
int[] destinationArray = new int[5];
System.arraycopy(sourceArray, 0, destinationArray, 0, sourceArray.length);
// 输出拷贝后的数组
for (int i = 0; i < destinationArray.length; i++) {
System.out.println("拷贝后的数组元素: " + destinationArray[i]);
}
以上代码首先声明了一个源数组 sourceArray
和一个目标数组 destinationArray
,然后使用 System.arraycopy()
方法将 sourceArray
中的所有元素拷贝到 destinationArray
中。最后,遍历 destinationArray
打印出数组的元素。
数组是Java中基础的数据结构,理解和掌握字符串与数组的操作对于成为高级Java开发者至关重要。后续章节将介绍更高级的数据结构和特性,例如集合框架和泛型编程,这将使数据处理更加灵活和强大。
7. Java高级特性应用
Java是一种成熟的、功能丰富的编程语言,随着Java 8及后续版本的推出,Java语言引入了大量高级特性,极大地丰富了Java应用的开发能力。这一章节将详细介绍这些高级特性的应用方法和使用场景。
7.1 集合框架的使用
集合框架是Java库中用于存储和操作对象集合的一组接口和类。了解如何使用这些集合是Java编程的核心部分。
7.1.1 List、Set、Map接口及其实现
-
List
接口下的实现如ArrayList
和LinkedList
都提供了按照插入顺序存储元素的能力,区别在于内部数据结构及性能表现。 -
Set
接口保证了集合中不会有重复的元素,HashSet
通常通过散列来实现快速检索,而TreeSet
则是通过红黑树维护元素的有序性。 -
Map
接口包含HashMap
和TreeMap
等,允许存储键值对,其中HashMap
基于哈希表,而TreeMap
保持键的排序。
import java.util.*;
public class CollectionsDemo {
public static void main(String[] args) {
// 使用List
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
// 使用Set
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
// 使用Map
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
}
}
7.1.2 集合的排序与搜索
Java集合框架提供了一些工具类,如 Collections
和 Arrays
,用于集合的排序与搜索。
import java.util.*;
public class CollectionsSearchSortDemo {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>();
numbers.add(3);
numbers.add(1);
numbers.add(2);
// 排序
Collections.sort(numbers);
// 搜索
int index = Collections.binarySearch(numbers, 2);
System.out.println("Index of 2: " + index);
}
}
7.2 IO流与文件处理
Java提供了强大的IO流支持,允许开发者以一致的方式读写不同类型的数据。
7.2.1 IO流的分类与使用
IO流分为字节流和字符流,分别由 InputStream
/ OutputStream
和 Reader
/ Writer
抽象类表示。
import java.io.*;
public class IoStreamDemo {
public static void main(String[] args) throws IOException {
// 字节流示例
FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt");
byte[] buffer = new byte[1024];
int length;
while ((length = fis.read(buffer)) != -1) {
fos.write(buffer, 0, length);
}
fos.close();
fis.close();
// 字符流示例
FileReader fr = new FileReader("input.txt");
FileWriter fw = new FileWriter("output.txt");
char[] cbuf = new char[1024];
int length;
while ((length = fr.read(cbuf)) != -1) {
fw.write(cbuf, 0, length);
}
fw.close();
fr.close();
}
}
7.2.2 文件操作与NIO
Java NIO(New IO)提供了比传统IO更高效、更灵活的IO操作方式,特别是在处理大量数据时。
import java.nio.file.*;
import java.nio.*;
public class NioFileDemo {
public static void main(String[] args) {
Path path = Paths.get("file.txt");
// 写入数据
String content = "Hello, NIO!";
try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.WRITE)) {
ByteBuffer buffer = Charset.defaultCharset().encode(content);
fileChannel.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
// 读取数据
try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ)) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
fileChannel.read(buffer);
buffer.flip();
String content = Charset.defaultCharset().decode(buffer).toString();
System.out.println(content);
} catch (IOException e) {
e.printStackTrace();
}
}
}
7.3 多线程编程技术
Java提供了完善的多线程支持,通过 Thread
类或 Runnable
接口来创建线程。
7.3.1 线程的创建与管理
可以通过扩展 Thread
类或实现 Runnable
接口来创建线程。
public class MyThread extends Thread {
public void run() {
// 执行代码
System.out.println("Thread is running!");
}
}
public class ThreadDemo {
public static void main(String[] args) {
Thread myThread = new MyThread();
myThread.start();
}
}
7.3.2 同步机制与线程协作
synchronized
关键字用于控制多个线程对共享资源的访问, wait()
和 notify()
方法用于线程之间的协作。
public class SynchronizedDemo {
private int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
public void decrement() {
synchronized (this) {
count--;
}
}
}
7.4 网络编程基础
Java提供了丰富的API用于网络编程,其中 ***
包是核心,包含了用于URL处理和套接字编程的类。
7.4.1 套接字编程与URL处理
使用 Socket
和 ServerSocket
类来实现基于TCP的客户端和服务器端。
``` .*;
public class SimpleServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(1234); System.out.println("Server started...");
Socket clientSocket = serverSocket.accept();
System.out.println("Client connected!");
// 处理客户端请求...
clientSocket.close();
serverSocket.close();
}
}
### 7.4.2 网络服务的开发与客户端
可以使用 `URL` 和 `URLConnection` 类来发送和接收网络资源。
```***
***.*;
public class SimpleClient {
public static void main(String[] args) throws IOException {
URL url = new URL("***");
URLConnection connection = url.openConnection();
connection.connect();
// 读取数据...
connection.disconnect();
}
}
7.5 反射机制应用
Java的反射机制允许程序在运行时访问和操作类、方法和字段。
7.5.1 反射的基本用法与优势
反射可以动态创建对象、访问和调用方法或字段,但会降低性能并需要谨慎使用。
public class ReflectionDemo {
public static void main(String[] args) {
try {
Class<?> cls = Class.forName("java.lang.String");
Constructor<?> constructor = cls.getConstructor(StringBuffer.class);
Object obj = constructor.newInstance(new StringBuffer("Reflection"));
System.out.println(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
}
7.5.2 动态代理与注解处理
反射常用于动态代理的创建,以及注解的解析。
import java.lang.reflect.*;
public class DynamicProxyDemo {
public static void main(String[] args) {
Object proxyInstance = Proxy.newProxyInstance(
DynamicProxyDemo.class.getClassLoader(),
new Class<?>[] {SomeInterface.class},
(proxy, method, args1) -> "Hello,反射代理!");
System.out.println(proxyInstance);
}
}
7.6 泛型编程
Java泛型提供了编译时类型安全检测机制,以避免强制类型转换的错误。
7.6.1 泛型类与方法
泛型类和方法可以在编译时期提供类型检查。
public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
7.6.2 类型擦除与通配符
泛型信息在运行时被擦除,使用通配符可以提供更灵活的泛型方法使用方式。
public static void processElements(List<?> list) {
for(Object o : list) {
System.out.println(o);
}
}
7.7 注解的使用
注解是一种元数据形式,可以应用于代码中的元素,如类、方法和变量。
7.7.1 注解的定义与应用
通过 @interface
关键字定义注解,然后使用 @Retention
、 @Target
等元注解来控制注解的生命周期和应用目标。
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String value();
}
7.7.2 元注解与自定义注解处理器
自定义注解处理器可以用于检查和执行注解指令。
import java.lang.reflect.*;
public class AnnotationProcessor {
public static void main(String[] args) throws Exception {
Method method = MyClass.class.getMethod("myMethod");
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
if (myAnnotation != null) {
System.out.println("Annotation value: " + myAnnotation.value());
}
}
}
class MyClass {
@MyAnnotation(value = "Test")
public void myMethod() {
}
}
7.8 Java 8新特性概览
Java 8是Java发展史上的一个重要版本,引入了Lambda表达式、函数式接口、Stream API等新特性。
7.8.1 Lambda表达式与函数式接口
Lambda表达式简化了接口的匿名实现,函数式接口则专为Lambda表达式设计。
import java.util.function.*;
public class LambdaDemo {
public static void main(String[] args) {
Consumer<String> consumer = (str) -> System.out.println(str);
consumer.accept("Hello, Lambda!");
}
}
7.8.2 Stream API与并行流处理
Stream API提供了现代的集合操作方式,支持顺序和并行处理。
import java.util.*;
import java.util.stream.Collectors;
public class StreamDemo {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c");
List<String> filteredList = list.stream()
.filter(str -> str.contains("a"))
.collect(Collectors.toList());
System.out.println(filteredList);
}
}
7.8.3 新时间日期API与Optional类
Java 8引入了新的日期和时间API,增强了日期和时间的处理能力, Optional
类则用于避免空指针异常。
import java.time.*;
import java.util.Optional;
public class DateTimeDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime dateTime = LocalDateTime.of(date, time);
Optional<LocalDate> optionalDate = Optional.ofNullable(LocalDate.now());
optionalDate.ifPresent(System.out::println);
}
}
Java高级特性是Java开发者的利器。这些特性简化了代码,提高了效率,使得Java应用的开发更加灵活和强大。掌握这些特性,对于提升Java开发者的竞争力至关重要。
简介:Java是广泛应用于企业级应用开发的流行编程语言。这份笔记详细介绍了Java的基础知识,从环境配置到面向对象编程,再到异常处理、集合框架、IO流、多线程等高级主题。通过学习这些关键知识点,初学者能迅速入门Java编程,并为深入学习奠定基础。