文章目录
- 一、面向对象的概念
- 二、类和对象
- 1. 如何定义/使用类
- 2. 定义类的补充注意事项
- 三、面向对象三大特征
- 1. 封装
- 2. 继承
- 2.1 例子
- 2.2 继承类型
- 2.3 继承的特性
- 2.4 继承中的关键字
- 2.4.1 extend
- 2.4.2 implements
- 2.4.3 super/this
- 2.4.4 final
- 3. 多态
- 4. 抽象类
- 4.1 抽象类
- 4.2 抽象方法
- 四、 接口
- 1. 接口和类的异同
- 2. 抽象类和接口的区别
- 3. 接口的声明/实现
- 五、 集合框架
- 1. 集合与数组的区别
- 2. 集合接口
- 3. Set和List的区别
- 4. ArrayList
- 5. LinkedList
- 六、泛型
- 七、文件管理
- 1. 文件操作
- 1.1 读取文件内容
- 1.2 写入文件
- 1.3 复制文件
- 1.4 移动文件
- 1.5 删除文件
- 2. 文件夹操作
- 2.1 创建文件夹
- 2.2 列出文件夹内容
- 2.3 删除文件夹
- 2.4 遍历文件夹
- 八、多线程
- 1. 线程的生命周期
- 2. 创建线程
- 九、小结
一、面向对象的概念
面向对象编程(Object-Oriented Programming,OOP)是一种编程方法,其中程序是由对象组成的。面向对象的编程的核心思想是,将程序中的实体、数据和功能抽象为单独的对象,并在这些对象之间建立联系。
面向对象方法的主要方面包括:
-
继承:子类继承父类的属性和方法,并可以添加新的属性和方法。
-
封装:对象的内部状态和行为被隐藏在对象内部,只能通过公共的方法访问。
-
多态:同一个方法可以有不同的实现,根据不同的对象类型而有不同的行为。
-
抽象:通过抽象类和接口来定义对象的公共行为,但不实现该行为。
-
关联:对象之间的关系,例如一对多,多对一等。
这些方面可以使程序更易于维护、扩展和重用,并使代码更具可读性和清晰度。面向对象的方法已经成为现代编程的重要方法,并应用于各种领域,如桌面应用程序、移动应用程序、游戏等。
二、类和对象
- 类:是对象共同特征的描述,描述一类对象的行为和状态。
- 对象:对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
1. 如何定义/使用类
在Java当中,必须先设计类,才能获取对象。
模板如下:
public void 类名{
变量
方法
}
如何调用模板如下:
类名 对象名 = new 类名();
那么改如何创建一个对象呢?
public class Phone{
// 属性(成员变量)
String brand;
double price;
// 方法
public void call(){
}
public void playGame(){
}
}
如何得到类的对象呢?
Phone p = new Phone();
- 调用属性:对象名.成员变量
- 调用方法:对象名.方法()
2. 定义类的补充注意事项
-
用来描述一类事物的类,专业叫做:javabean类,在Javabean类中,是不写main方法的
-
而以前编写main方法的类,叫做测试类。可以在测试类中创建Javabean类的对象并进行赋值调用
- 类名首字母大写,见名知意,小驼峰
- 一个Java文件可以定义多个class类,且一个类只能用一个public修饰,且public修饰的类名必须成为代码文件名(实际开发中,还是一个文件定义一个类)
- 成员变量的定义完整格式是:修饰符 数据类型 变量名 = 初始值;
三、面向对象三大特征
1. 封装
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
要访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于能修改自己的实现代码,而不用修改那些调用代码的程序片段。
适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。
封装的优点:
-
良好的封装能够减少耦合。
-
类内部的结构可以自由修改。
-
可以对成员变量进行更精确的控制。
-
隐藏信息,实现细节。
1.修改属性的可见性来限制对属性的访问(一般限制为private),例如:
public class Person {
private String name;
private int age;
}
这段代码中,将 name 和 age 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。
2.对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:
public class Person{
private String name;
private int age;
public int getAge(){
return age;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public void setName(String name){
this.name = name;
}
}
采用 this 关键字是为了解决实例变量和局部变量之间发生的同名的冲突。
实例:
/* 文件名: EncapTest.java */
public class Test{
private String name;
private String idNum;
private int age;
public int getAge(){
return age;
}
public String getName(){
return name;
}
public String getIdNum(){
return idNum;
}
public void setAge( int newAge){
age = newAge;
}
public void setName(String newName){
name = newName;
}
public void setIdNum( String newId){
idNum = newId;
}
}
其实说白了就是把变量进行一次封装加密,隐藏了实现过程,提供了一个get和set方法来使用,后续可以使用注解来简化
2. 继承
2.1 例子
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
下面用父亲有两个儿子来举例:
父亲类:
public class Father extends Father{
private String name;
private int age;
public Father(String myName,int Myage){
name = myName;
age = myAge;
}
public void eat(){
System.out.println(name+"要吃苹果");
}
public void introduction() {
System.out.println("大家好!我是"+name+"今年"+age+"岁");
}
}
大儿子类
public class Bigson extends Father{
public Bigson (String myName, int myAge) {
super(myName, myAge);
}
}
小儿子类
public class Smallson extends Father{
public Smallson (String myName, int myAge) {
super(myName, myAge);
}
}
在上面代码中,Father类就是可以作为一个父类,当大儿子和二儿子继承父类后,就具有父类的属性和方法,子类就不会存在重复的代码,维护性也提高,代码也更加简洁,提高代码的复用性
2.2 继承类型
java不支持多继承,但是可以多重继承,例如
- A继承B,B继承C
- A继承C,B继承C
- 但是不可以 A继承B,A继承C
2.3 继承的特性
-
子类拥有父类非 private 的属性、方法。
-
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
-
子类可以用自己的方式实现父类的方法。
-
Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
-
提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
2.4 继承中的关键字
2.4.1 extend
在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。
public class Father {
private String name;
private int age;
public Father (String myName, int myAge) {
//初始化属性值
}
public void eat() { //吃东西方法的具体实现 }
public void sleep() { //睡觉方法的具体实现 }
}
public class Bigson extends Father{
}
2.4.2 implements
使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。
public interface A {
public void eat();
public void sleep();
}
public interface B {
public void show();
}
public class C implements A,B {
}
2.4.3 super/this
super关键字:可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用。
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this 调用自己的方法
super.eat(); // super 调用父类方法
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eatTest();
}
}
输出结果:
animal : eat
dog : eat
animal : eat
2.4.4 final
final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。
final 含义为 “最终的”。
使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写:
- 声明类:
final class 类名 {//类体}
- 声明方法:
修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}
注: final 定义的类,其中的属性、方法不是 final 的。
3. 多态
多态是同一个行为具有多个不同表现形式或形态的能力。
例如父亲与两个儿子的故事:
public void Father(){
public void eat{
System.out.println("我喜欢吃鸭头")}
}
public void Bigson extends Father(){
public void eat{
System.out.println("我喜欢吃鸭肉")}
}
public void Smallson extends Father(){
public void eat{
System.out.println("我喜欢吃鸭腿");
}
}
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理
实例:
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
运行结果:
4. 抽象类
4.1 抽象类
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
在 Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
但是说白了其实定义类的过程就是抽象和封装的过程,而抽象类与接口则是对实体类进行更高层次的抽象,仅定义公共行为和特征
在 Java 语言中使用 abstract class 来定义抽象类。如下实例:
public abstract class Employee
{
private String name;
private String address;
private int number;
public Employee(String name, String address, int number)
{
System.out.println("Constructing an Employee");
this.name = name;
this.address = address;
this.number = number;
}
public double computePay()
{
System.out.println("Inside Employee computePay");
return 0.0;
}
public void mailCheck()
{
System.out.println("Mailing a check to " + this.name
+ " " + this.address);
}
public String toString()
{
return name + " " + address + " " + number;
}
public String getName()
{
return name;
}
public String getAddress()
{
return address;
}
public void setAddress(String newAddress)
{
address = newAddress;
}
public int getNumber()
{
return number;
}
}
4.2 抽象方法
如果一个类没有足够的信息去描述一个具体的类,那就称之为抽象类,定义一个宽泛的范围去定义,比如定义大象为动物类,动物类就是抽象类
如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。
public abstract class Employee
{
private String name;
private String address;
private int number;
public abstract double computePay();
//其余代码
}
声明抽象方法会造成以下两个结果
- 如果一个类包含抽象方法,那么该类必须是抽象类。
- 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。
抽象类总结规定
-
- 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
-
- 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
-
- 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
-
- 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
-
- 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
四、 接口
在软件中,接口同样是一种规范和标准,它们可以约束类的行为,是一些方法特征的业合,但没有方法的实现。需要类对接口进行实现
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
1. 接口和类的异同
接口 和 类 的相同点:
- 一个接口可以有多个方法。
- 接口文件保存在 .java 结尾的文件中,文件名使用接口名。
- 接口的字节码文件保存在 .class 结尾的文件中。
- 接口相应的字节码文件必须在与包名称相匹配的目录结构中。
接口 和 类 的不同点:
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法,Java 8 之后 接口中可以使用 default关键字修饰的非抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。
更多说明:
2. 抽象类和接口的区别
抽象类和接口的区别:
-
- 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
-
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
-
- 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
-
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
3. 接口的声明/实现
接口的声明
- 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
- 接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
- 接口中的方法都是公有的。
[访问修饰符] interface 接口名称 [extends 其他的接口名] {
// 声明变量
// 抽象方法
}
接口的实现
当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。
类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。
实现一个接口的语法,可以使用这个公式:
public class 类名 implements 接口名称[, 其他接口名称, 其他接口名称..., ...] ...
下面举一个简单的例子:
接口的声明:
interface Animal {
public void eat();
public void travel();
}
接口的实现
/* 文件名 : MammalInt.java */
public class MammalInt implements Animal{
public void eat(){
System.out.println("Mammal eats");
}
public void travel(){
System.out.println("Mammal travels");
}
public int noOfLegs(){
return 0;
}
public static void main(String args[]){
MammalInt m = new MammalInt();
m.eat();
m.travel();
}
}
再次注意,重写接口中声明的方法时,需要注意以下规则:
- 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
- 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
- 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。
在实现接口的时候,也要注意一些规则: - 一个类可以同时实现多个接口。
- 一个类只能继承一个类,但是能实现多个接口。
- 一个接口能继承另一个接口,这和类之间的继承比较相似。
五、 集合框架
1. 集合与数组的区别
数组:
- 长度是固定的
- 可以存储基本数据类型,也可也存储对象的引用
- 对象必须是相同类型的数据
集合:
- 长度是可变的
- 只能用于存储对象的引用
- 对象可以是不同类型的数据
为了方便多个对象的操作,就可以将对象进行存储,集合就是存储对象最常用的一种方式。
集合框架被设计成要满足以下几个目标。
- 该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。
- 该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
- 对一个集合的扩展和适应必须是简单的。
2. 集合接口
集合接口:
序号 | 接口 | 接口描述 |
---|---|---|
1 | Collection 接口 | Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。Collection 接口存储一组不唯一,无序的对象。 |
2 | List 接口 | List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。List 接口存储一组不唯一,有序(插入顺序)的对象。 |
3 | Set | Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。Set 接口存储一组唯一,无序的对象。 |
4 | SortedSet | 继承于Set保存有序的集合。 |
5 | Map | Map 接口存储一组键值对象,提供key(键)到value(值)的映射。 |
6 | Map.Entry | 描述在一个Map中的一个元素(键/值对)。是一个 Map 的内部接口。 |
7 | SortedMap | 继承于 Map,使 Key 保持在升序排列。 |
8 | Enumeration | 这是一个传统的接口和定义的方法,通过它可以枚举(一次获得一个)对象集合中的元素。这个传统接口已被迭代器取代。 |
3. Set和List的区别
Set和List的区别
-
Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
-
Set 检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。
-
List 和数组类似,可以动态增长,根据实际存储的数据的长度自动增长 List 的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> 。
4. ArrayList
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,可以添加或删除元素。
ArrayList 继承了 AbstractList ,并实现了 List 接口。
ArrayList 类位于 java.util 包中,使用前需要引入它,语法格式如下:
import java.util.ArrayList; // 引入 ArrayList 类
ArrayList<E> objectName =new ArrayList<>(); // 初始化
- E: 泛型数据类型,用于设置 objectName 的数据类型,只能为引用数据类型。
- objectName: 对象名。
ArrayList 类提供了很多有用的方法,常用的几个如下:
具体的见下表
Java ArrayList 方法
Java ArrayList 常用方法列表如下:
方法 | 描述 |
---|---|
add() | 将元素插入到指定位置的 arraylist 中 |
addAll() | 添加集合中的所有元素到 arraylist 中 |
clear() | 删除 arraylist 中的所有元素 |
clone() | 复制一份 arraylist |
contains() | 判断元素是否在 arraylist |
get() | 通过索引值获取 arraylist 中的元素 |
indexOf() | 返回 arraylist 中元素的索引值 |
removeAll() | 删除存在于指定集合中的 arraylist 里的所有元素 |
remove() | 删除 arraylist 里的单个元素 |
size() | 返回 arraylist 里元素数量 |
isEmpty() | 判断 arraylist 是否为空 |
subList() | 截取部分 arraylist 的元素 |
set() | 替换 arraylist 中指定索引的元素 |
sort() | 对 arraylist 元素进行排序 |
toArray() | 将 arraylist 转换为数组 |
toString() | 将 arraylist 转换为字符串 |
ensureCapacity() | 设置指定容量大小的 arraylist |
lastIndexOf() | 返回指定元素在 arraylist 中最后一次出现的位置 |
retainAll() | 保留 arraylist 中在指定集合中也存在的那些元素 |
containsAll() | 查看 arraylist 是否包含指定集合中的所有元素 |
trimToSize() | 将 arraylist 中的容量调整为数组中的元素个数 |
removeRange() | 删除 arraylist 中指定索引之间存在的元素 |
replaceAll() | 将给定的操作内容替换掉数组中每一个元素 |
removeIf() | 删除所有满足特定条件的 arraylist 元素 |
forEach() | 遍历 arraylist 中每一个元素并执行特定操作 |
其他的引用类型
ArrayList 中的元素实际上是对象,数组列表元素都是字符串 String 类型。
如果要存储其他类型,而 <E> 只能为引用数据类型,这时就需要使用到基本类型的包装类。
基本类型对应的包装类表如下:
基本类型 | 引用类型 |
---|---|
boolean | Boolean |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
5. LinkedList
Java LinkedList(链表) 类似于 ArrayList,是一种常用的数据容器。
与 ArrayList 相比,LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低。
以下情况使用 ArrayList :
- 频繁访问列表中的某一个元素。
- 只需要在列表末尾进行添加和删除元素操作。
以下情况使用 LinkedList :
- 需要通过循环迭代来访问列表中的某些元素。
- 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
LinkedList 类位于 java.util 包中,使用前需要引入它,语法格式如下:
// 引入 LinkedList 类
import java.util.LinkedList;
LinkedList<E> list = new LinkedList<E>(); // 普通创建方法
或者
LinkedList<E> list = new LinkedList(Collection<? extends E> c); // 使用集合创建链表
创建一个简单的链表实例:
// 引入 LinkedList 类
import java.util.LinkedList;
public class RunoobTest {
public static void main(String[] args) {
LinkedList<String> sites = new LinkedList<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Weibo");
System.out.println(sites);
}
}
结果如下:
[Google, Runoob, Taobao, Weibo]
方法 | 描述 |
---|---|
public boolean add(E e) | 链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public void add(int index, E element) | 向指定位置插入元素。 |
public boolean addAll(Collection c) | 将一个集合的所有元素添加到链表后面,返回是否成功,成功为 true,失败为 false。 |
public boolean addAll(int index, Collection c) | 将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。 |
public void addFirst(E e) | 元素添加到头部。 |
public void addLast(E e) | 元素添加到尾部。 |
public boolean offer(E e) | 向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerFirst(E e) | 头部插入元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerLast(E e) | 尾部插入元素,返回是否成功,成功为 true,失败为 false。 |
public void clear() | 清空链表。 |
public E removeFirst() | 删除并返回第一个元素。 |
public E removeLast() | 删除并返回最后一个元素。 |
public boolean remove(Object o) | 删除某一元素,返回是否成功,成功为 true,失败为 false。 |
public E remove(int index) | 删除指定位置的元素。 |
public E poll() | 删除并返回第一个元素。 |
public E remove() | 删除并返回第一个元素。 |
public boolean contains(Object o) | 判断是否含有某一元素。 |
public E get(int index) | 返回指定位置的元素。 |
public E getFirst() | 返回第一个元素。 |
public E getLast() | 返回最后一个元素。 |
public int indexOf(Object o) | 查找指定元素从前往后第一次出现的索引。 |
public int lastIndexOf(Object o) | 查找指定元素最后一次出现的索引。 |
public E peek() | 返回第一个元素。 |
public E element() | 返回第一个元素。 |
public E peekFirst() | 返回头部元素。 |
public E peekLast() | 返回尾部元素。 |
public E set(int index, E element) | 设置指定位置的元素。 |
public Object clone() | 克隆该列表。 |
public Iterator descendingIterator() | 返回倒序迭代器。 |
public int size() | 返回链表元素个数。 |
public ListIterator listIterator(int index) | 返回从指定位置开始到末尾的迭代器。 |
public Object[] toArray() | 返回一个由链表元素组成的数组。 |
public T[] toArray(T[] a) | 返回一个由链表元素转换类型而成的数组。 |
六、泛型
可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。
下面是定义泛型方法的规则:
- 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的 )。
- 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
- 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
- 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像 int、double、char 等)。
java 中泛型标记符:
- E - Element (在集合中使用,因为集合中存放的是元素)
- T - Type(Java 类)
- K - Key(键)
- V - Value(值)
- N - Number(数值类型)
- ? - 表示不确定的 java 类型
public class GenericMethodTest
{
// 泛型方法 printArray
public static < E > void printArray( E[] inputArray )
{
// 输出数组元素
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}
public static void main( String args[] )
{
// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println( "整型数组元素为:" );
printArray( intArray ); // 传递一个整型数组
System.out.println( "\n双精度型数组元素为:" );
printArray( doubleArray ); // 传递一个双精度型数组
System.out.println( "\n字符型数组元素为:" );
printArray( charArray ); // 传递一个字符型数组
}
}
运行如下:
整型数组元素为:
1 2 3 4 5
双精度型数组元素为:
1.1 2.2 3.3 4.4
字符型数组元素为:
H E L L O
七、文件管理
文件和文件夹操作是常见的任务之一。可能需要读取、写入、创建、删除文件或文件夹,以及遍历文件系统中的内容。
1. 文件操作
1.1 读取文件内容
在Java中,你可以使用FileInputStream
或BufferedReader
来读取文件内容。以下是一个读取文本文件内容的示例:
import java.io.*;
public class ReadFileExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
1.2 写入文件
要将数据写入文件,可以使用FileOutputStream
或BufferedWriter
,例子如下:
·
import java.io.*;
public class WriteFileExample {
public static void main(String[] args) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
writer.write("Hello, World!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
1.3 复制文件
要复制文件,可以逐个字节或块地复制文件内容。这是一个逐个字节复制文件的示例:
import java.io.*;
public class CopyFileExample {
public static void main(String[] args) {
try (FileInputStream inputStream = new FileInputStream("source.txt");
FileOutputStream outputStream = new FileOutputStream("destination.txt")) {
int byteRead;
while ((byteRead = inputStream.read()) != -1) {
outputStream.write(byteRead);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
1.4 移动文件
要移动文件,可以使用File
类的renameTo()
方法
import java.io.File;
public class MoveFileExample {
public static void main(String[] args) {
File sourceFile = new File("source.txt");
File destinationFile = new File("destination.txt");
if (sourceFile.renameTo(destinationFile)) {
System.out.println("文件移动成功");
} else {
System.out.println("文件移动失败");
}
}
}
1.5 删除文件
要删除文件,可以使用File类的delete()方法。示例如下:
import java.io.File;
public class DeleteFileExample {
public static void main(String[] args) {
File fileToDelete = new File("fileToDelete.txt");
if (fileToDelete.delete()) {
System.out.println("文件删除成功");
} else {
System.out.println("文件删除失败");
}
}
}
2. 文件夹操作
2.1 创建文件夹
要创建文件夹,可以使用File类的mkdir()或mkdirs()方法。mkdir()只会创建一个文件夹,而mkdirs()会创建多层文件夹(如果父文件夹不存在)。示例如下:
import java.io.File;
public class CreateDirectoryExample {
public static void main(String[] args) {
File newDirectory = new File("newDirectory");
if (newDirectory.mkdir()) {
System.out.println("文件夹创建成功");
} else {
System.out.println("文件夹创建失败");
}
}
}
2.2 列出文件夹内容
要列出文件夹的内容,可以使用File类的list()或listFiles()方法。list()返回文件名的字符串数组,listFiles()返回File对象数组。以下是一个列出文件夹内容的示例:
import java.io.File;
public class ListFilesExample {
public static void main(String[] args) {
File directory = new File("myDirectory");
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
System.out.println(file.getName());
}
}
}
}
2.3 删除文件夹
要删除文件夹,可以使用File类的delete()方法。删除文件夹之前,必须确保文件夹为空。以下是一个删除文件夹的示例:
import java.io.File;
public class DeleteDirectoryExample {
public static void main(String[] args) {
File directoryToDelete = new File("directoryToDelete");
if (directoryToDelete.delete()) {
System.out.println("文件夹删除成功");
} else {
System.out.println("文件夹删除失败");
}
}
}
2.4 遍历文件夹
遍历文件夹是一种常见的任务,可以使用递归或栈来实现。以下是一个使用递归遍历文件夹的示例:
import java.io.File;
public class TraverseDirectoryExample {
public static void main(String[] args) {
File directory = new File("myDirectory");
traverse(directory);
}
public static void traverse(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
for (File subFile : files) {
traverse(subFile);
}
}
} else {
System.out.println(file.getName());
}
}
}
八、多线程
Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。
多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。
1. 线程的生命周期
-
新建状态:
使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
-
就绪状态:
当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
-
运行状态:
如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
-
阻塞状态:
如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
-
等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
-
同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
-
其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
-
-
死亡状态:
一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。
2. 创建线程
创建一个线程,最简单的方法是创建一个实现 Runnable 接口的类。
为了实现 Runnable,一个类只需要执行一个方法调用 run(),声明如下:
public void run()
具体实例如下:
class RunnableDemo implements Runnable {
private Thread t;
private String threadName;
RunnableDemo( String name) {
threadName = name;
System.out.println("Creating " + threadName );
}
public void run() {
System.out.println("Running " + threadName );
try {
for(int i = 4; i > 0; i--) {
System.out.println("Thread: " + threadName + ", " + i);
// 让线程睡眠一会
Thread.sleep(50);
}
}catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
public class TestThread {
public static void main(String args[]) {
RunnableDemo R1 = new RunnableDemo( "Thread-1");
R1.start();
RunnableDemo R2 = new RunnableDemo( "Thread-2");
R2.start();
}
}
运行如下:
Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.
九、小结
写本文主要是为了分享我的学习过程,也是给自己记个笔记,哪里忘记了,回来再看一眼,也可以很快的回想起来