Java学习笔记(2)
# Object类
Object(java.lang)
类是所有类的根类,它其中的所有方法子类都可以使用,如果一个类没有指定父类,则该类默认继承自Object
类。
public static MyClass /*extends Object*/ {
···
}
2
3
# toString方法
如果直接调用一个对象的toString
方法,会打印这个对象的地址值,如果我们想要该方法实现其他功能(比如要打印属性的值等等),就需要对该方法进行重写。
# equals方法
equals
方法中的比较使用的是==
号,对于这个运算符:
- 比较的是基本数据类型:比较值
- 比较的是引用数据类型:比较的是地址值
# Objects类
# equals方法
Objects
类是JDK7中添加的一个工具类,它提供了一些方法来操作对象,这些方法是*null safe(空指针安全)或者null-tolerant(容忍空指针的)*的。
比如Object
类中的equals
方法有时会抛出空指针异常,而Objects
类中的equals
方法就优化了这个方法,源码如下:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && q.equals(b));
}
2
3
# System类
# arraycopy方法
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
2
3
可以实现将一个数组中的元素拷贝到另一个数组中,其参数:
- src:源数组
- srcPos:源数组中的起始位置
- dest:目标数组
- destPos:目标数组起始位置
- length:复制的元素的个数
# 包装类
基本类型 | 对应的包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
# 装箱和拆箱
- 装箱:从基本类型转换为对应的包装类对象
- 拆箱:从包装类对象转换为对应的基本类型
# 自动装箱和自动拆箱
Integer in = 123; // 相当于 Integer in = new Integer(123);
in = in + 2; // 相当于 in.intValue() = in.intValue() + 2;
ArrayList<Integer> integerList = new ArrayList<>();
integerList.add(123); // 相当于 integerList.add(new Integer(1));
2
3
4
5
6
# 基本数据类型和字符串之间的转换
最简单的一种方式就是基本数据类型之间和空字符串连接:
String str = 123 + "";
System.out.println(str.getClass()); // class java.lang.String
2
字符串转换为其他基本类型:
除了Character
类之外,其他所有基本类型都有parse{xxxx}
的静态方法可以把字符串参数转换为对应的基本类型
public static byte ParseByte(String s);
public static int parseInt(String s);
······
2
3
4
5
# Collection
常用的共有方法:
public class Demo1 {
public static void main(String[] args) {
// 创建Collection对象可以使用多态
Collection<Object> collection = new ArrayList<>();
// boolean add(E e); 添加元素
collection.add("test");
// 重写了toString方法
System.out.println(collection);
// boolean remove(Object o); 删除元素
collection.remove("test");
System.out.println(collection);
// boolean contains(Object o); 判断是否包含指定元素
System.out.println(collection.contains("test"));
// boolean isEmpty(); 判断当前集合是否为空
System.out.println(collection.isEmpty());
// int size(); 返回集合中元素的个数
System.out.println(collection.size());
// Object[] toArray(); 把集合中的元素变成数组
Object[] objects = collection.toArray();
// void clear(); 清空集合中的元素,不会删除集合
collection.clear();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Iterator
笔记
Iterator:迭代器
简单来说就是用来遍历集合的一个接口(Set接口实现的Collection接口没有索引,无法使用for循环遍历)
一般来说,迭代器的原理就是:在去元素之前要判断集合中有没有元素,如果有,则把这个元素取出来,再重复判断流程,直到集合中的元素全部取出
public class Demo1 {
public static void main(String[] args) {
// 创建Collection对象可以使用多态
Collection<Object> collection = new ArrayList<>();
// boolean add(E e); 添加元素
collection.add("test");
collection.add("test2");
collection.add("test3");
// 获取迭代器对象,并遍历集合(增强for循环)
for (Object next : collection) {
System.out.println(next);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 泛型
笔记
泛型是一种未知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型。
泛型也可以看作一个变量,用来接收数据类型。
以ArrayList
类为例:
// ArrayList类的声明
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
2
3
4
在创建集合对象的时候,就会确定泛型的数据类型,比如下面的代码就确定了泛型为String
ArrayList<String> list = new ArrayList<String>();
如果创建一个集合对象不使用泛型的时候,那么会存在下面的两点:
- 好处:默认类型为
Object
,可以存储任意类型的数据 - 弊端:不安全,可能会引发异常
# 定义含有泛型的类
public class GenericClass<E> {
private E name;
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
}
2
3
4
5
6
7
8
9
10
11
# 定义含有泛型的方法
public class GenericClass {
public <M> void method1(M m) {
System.out.println(m.getClass());
}
public static void main(String[] args) {
GenericClass genericClass = new GenericClass();
genericClass.method1(123);
genericClass.method1("F4de");
}
}
2
3
4
5
6
7
8
9
10
11
# 泛型通配符
笔记
如果泛型类型不确定,可以通过通配符<?>
来表示。但是一旦使用泛型通配符之后,就只能使用Object类
中的共性方法,集合中元素自身方法无法使用。
现在定义一个方法,用来遍历不同类型的集合中的元素,就要使用到通配符
public class GenericClass {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
ArrayList<String> strings = new ArrayList<>();
strings.add("123");
strings.add("456");
strings.add("789");
traverseCollection(integers);
traverseCollection(strings);
}
public static void traverseCollection(ArrayList<?> list) {
Iterator<?> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
泛型的限定
<? extends E>
:代表使用的泛型只能是E类型的子类或者本身<? super E>
:代表使用的泛型只能是E类型的父类或者本身
提示
在前面简单介绍了Collection
,下面开始学习它的两个子接口:List
和Set
# List
List接口的主要特点:
- 有序
- 有索引
- 允许存储重复的元素
它的一些共有的方法可以在API内文档中查询,由于比较容易理解和掌握,这里就不做示例了
# ArrayList
ArrayList
类在第一部分已经学习过了,这里直接跳过
# LinkedList
笔记
LinkedList是一个双向链表结构
里面包含了大量的操作首尾元素的方法,由于和C语言实现的双向链表功能差不多,所以这里不做太多示例,可参考在线API文档:https://www.matools.com/api/java8
# Vector
笔记
Vector类可以实现可增长的对象数组
https://www.matools.com/api/java8
# Set
Set
接口是一个不包含重复元素的Collection
,其特点如下:
- 不允许存储重复的元素
- 没有索引并且没有带索引的方法,无法使用普通的
for
循环进行遍历
# 异常处理
# 多线程
# 并发和并行
- 并发:指两个或多个事件在同一个时间段内发生
- 并行:指两个或多个事件在同一个时刻内发生
# 线程和进程
- 进程:简单来说就是内存中运行的应用程序,每个进程都有一个独立的内存空间
- 线程:线程是进程的执行单元,负责当前进程中程序的运行,一个进程至少有一个线程
# 线程调度
- 分时调度:所有线程轮流占有CPU的使用权
- 抢占式调度:优先让优先级高的线程使用CPU,如果线程优先级相同,那么会随机选择一个(线程随机)
笔记
java中的程序属于抢占式调度
# 创建线程类
- 创建一个Thread类的子类
- 在该子类中重写Thread的run方法,设置线程任务(就是开启线程之后要做什么)
- 创建Thread类的子类对象
- 调用子类对象中的start方法,开启新线程,执行线程任务
public class PracticeThread extends Thread {
// 重写run方法
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("子线程:" + i);
}
}
public static void main(String[] args) {
PracticeThread practiceThread = new PracticeThread();
practiceThread.start();
for (int i = 0; i < 20; i++) {
System.out.println("main线程:" + i);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
由于线程调度方式为抢占式调度,所以上述代码的每次执行结果都是不一样的