Java语言

Java介绍

Java语言是一种面向对象的高级语言。Java程序是在Java虚拟机上运行的,具有更好的安全性。
Java语言的源程序是以后缀.java结尾的文本文件,经过Java编译器(Javac)编译为.class的字节码文件,字节码是Java虚拟机(JVM)的机器语言。Java装载器将java字节码文件装载到Java虚拟机种运行。

Java平台

Java平台包括两个组件:

  • Java虚拟机
  • Java API

JDK、JRE和JVM

JVM就是Java虚拟机。JRE是Java运行环境,包括JVM和API。JDK是用Java开发应用程序所需要的软件开发工具包,包括JRE,还有Java开发工具如编译器Javac,字节码装载器Java,java文档工具等。

应用

Java用于开发移动应用程序、Web应用程序、桌面应用程序、游戏等。

基本数据类型

整数
byte
short
int
long
浮点数

float(4字节)
声明float变量时需要在浮点数后面加上F或f

double(8字节)
字符
char(2字节)
char的本质是一个整数,输出的是unicode编码对应的字符。
布尔型(1字节)
boolean
值为true和false
不能用0或非0数据代替false或true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class demo01 {
public static void main(String[] args) {
byte num1=127;
short num2 = 256;
int num3 = 512;
long num4 = 1024;
float num5 = 11.22F;
double num6 = 11.22;
char ch = 'a';
System.out.println(num1);
System.out.println(num2);
System.out.println(num3);
System.out.println(num4);
System.out.println(num5);
System.out.println(num6);
System.out.println(ch);
}
}
>>>
127
256
512
1024
11.22
11.22
a

Java修饰符

访问控制修饰符

  • default
    在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
  • private
    在同一类内可见。使用对象:变量、方法。
  • public
    对所有类可见。使用对象:类、接口、变量、方法。
  • protected
    对同一包内的类和所有子类可见。使用对象:变量、方法。

非访问控制修饰符

  • static修饰符
    • 静态变量
      声明独立于对象的静态变量
    • 静态方法
      声明独立于对象的静态方法
  • final修饰符
    • final变量
      被final修饰的变量一旦被赋值,不能被重新赋值,且被 final 修饰的实例变量必须显式指定初始值。
    • final方法
      父类中的 final 方法可以被子类继承,但是不能被子类重写。
    • final类
      final 类不能被继承,没有类能够继承 final 类的任何特性。

运算符表达式

键盘录入与输出

1
2
3
4
5
6
7
8
9
10
import java.util.Scanner;  //此代码必须出现在类定义的上边
public class Variabletest {
public static void main(String[] args){
Scanner sc=new Scanner(System.in); //sc是变量名
System.out.println("请输入年龄:");

int age=sc.nextInt(); //这里有类型的声明
System.out.println(age);
}
}
1
2
System.out.println();  //换行
System.out.print(); //不换行

运算符

+ - * / %
在+-*时如果有小数参与计算,结果可能不精确
/和%整数参与计算,结果是整数,小数参与计算结果可能不精确

赋值运算符

=
+=
-=
*=
/=
%=

关系运算符

==
!=
>
<
>=
<=
结果都是boolean类型,要么是true,要么是false。

逻辑运算符

&
|
^ 异或 相同为0,不同为1
! 取反
<< 左移 //向左移动,低位补0
>> 右移 //向右移动,高位补0或1,负数补1
>>> 无符号右移 //向右移动,高位补0

短路逻辑运算符

&& 短路与
|| 短路或
只要左边能确定整个表达式的结果,右边不执行。

字符串拼接

1
2
3
4
5
6
7
8
9
10
11
当"+"操作中出现字符串时,这时候时字符串连接。
String str="123";
int num=123;
str=str+num;
System.out.print(str);
>>>123123

连续进行"+"操作时,从左到又逐个执行
String str="123";
System.out.print(1+2+str);
>>>3123

字符+操作

1
2
3
4
5
6
7
8
        char a='a';
int result=a+'b';
System.out.print(result);
>>>195
char a='a';
int result=a+9;
System.out.print(result);
>>>106

自增自减

++
--

类型转换

隐式
byte→short→int→long→float→double
数据类型不一样,不能进行运算,需要转换成一样的才可以进行计算
取值范围小的数据,和取值范围大的数据进行运算,小的会先提升为大的之后,再进行运算
byte short char 三种数据在运算的时候,都会提升为int ,然后再进行运算
强制转换
从大范围到小范围,不能直接赋值。
格式:目标数据类型 变量名 = (目标数据类型)被强制转换的数据

1
2
3
4
5
6
7
8
9
10
11
        byte num1=100;
byte num2=100;
byte sum=(byte)(num1+num2);
System.out.print(sum);
>>>-56
这里得到的结果本应该是200,但是其对应类型是byte,有符号整数,其范围是-128~127
超出范围了
200对应的二进制是1100 1000
第一位是符号位,所以是负数,原码->反码->补码转换
1100 1000->1011 0111->1011 1000
0011 1000转换为十进制是56,带上符号位,就是-56

三元运算符

格式:关系表达式?表达式1:表达式2;
true返回表达式1,false返回表达式2。

运算符优先级

原码反码补码

原码:十进制的二进制表现形式,最左边是符号位,0为正,1为负。
原码对正数进行计算不会有问题。
但是如果对负数记算,结果会出错。

反码:正数的反码不变,负数的反码在原码的基础上,符号位不变。数值取反,0变1,1变0。
负数运算时如果结果跨0,会出现1的偏差

补码:正数的补码不变,负数的补码在反码的基础上+1。
补码还能多记录一个特殊的值-128,它在1个字节下,没有原码和反码。

1
2
int a=130;
byte b=(byte)a; //-126

计算机中的存储和计算都是以补码的形式进行的。

流程控制语句

顺序结构

从上往下依次执行

分支结构

if语句

1
2
3
if (关系表达式){
语句体;
}
1
2
3
4
5
if (关系表达式){
语句体1;
}else{
语句体2;
}
1
2
3
4
5
6
7
8
9
if (关系表达式1){
语句体1;
}else if(关系表达式2){
语句体2;
}
...
else{
语句体n+1;
}

switch语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
switch (表达式){
case 1:
语句体1;
break;
case 2:
语句体2;
break;
case 3:
语句体3;
break;
...
default:
语句体n+1;
break;
}

switch拓展

  • default的位置和省略
    位置不一定放在最后,放在其他位置和放在最后效果是一样的,省略的话如果所有的case都没有匹配上,switch就结束了
  • case穿透
    拿着小括号中的表达式和case进行匹配,匹配上之后执行对应语句体,遇到break,结束整个switch语句,但是如果没有break,会继续执行后面的case的语句体,甚至default中的语句体,直到遇到break为止。
  • switch新特性(简化写法)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    switch (){
    case 1->{
    语句体1;
    }
    case 2->{
    语句体2;
    }
    case 3->{
    语句体3;
    }
    default ->{
    语句体;
    }
    } //如果语句体只有一行,大括号可以省略

循环结构

for

1
2
3
4
5
6
7
for (int i=0;i<10;i++){
语句体;
}

for (初始化语句;条件判断语句;条件控制语句){
循环体;
}

while

1
2
3
4
while (条件判断语句){
循环体语句;
条件控制语句;
}

do while

1
2
3
4
do {
循环体语句;
条件控制语句;
}while(条件判断语句)

方法

方法(method)是程序中最小的执行单元。

main方法是主方法。metnod1是自己写的方法。
方法定义:将一些代码打包在一起,这个过程称为方法的定义。
方法调用:方法定义后不是直接运行的,需要手动调用才能执行。

1
2
3
4
public static 返回值类型 方法名 (参数){
方法体;
return 返回值;
}

有返回值方法的调用格式

直接调用
赋值调用
输出调用
注意事项
方法的返回值类型为void,表示该方法没有返回值,return语句可以省略不写,写了return 后面就不能跟具体的数据。
return 语句下面不能编写代码,因为执行不到,属于无效的代码。

方法的重载

在同一个类中,定义了多个同名的方法,这些同名的方法具有同种功能。
每个方法具有不同的参数类型或参数个数,这些同名的方法,就构成了重载的关系。
简记:在同一个类中,方法名相同,参数不同的方法。与返回值无关。
参数不同:个数不同,类型不同,顺序不同

方法调用的基本原理

调用方法时,方法会进入栈中,先进后出的原理。
方法执行时入栈,执行完毕出栈。

基本数据类型和引用数据类型

基本
整数
浮点数
布尔
字符
引用
除了基本都是引用

方法的值传递和址传递

面向对象

类和对象

一个java文件里面只能有一个公有类
类的定义

1
2
3
public class ClassName{

}

对象
类的实例,有属性和方法
创建对象

1
ClassName className = new ClassName();

构造方法

构造方法名与类名一致,没有返回值
在创建对象的时候会自动被调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Stu {
String id;
String name;
int age;
public Stu(){
// 默认的构造方法
}

public Stu(String id,String name,int age){
this.id=id;
this.name=name;
this.age=age;
}

public static void main(String[] args) {
Stu stu = new Stu("001","stu1",21);
}
}

成员方法

需要实例化对象,通过对象来调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Stu {
String id;
String name;
int age;
public Stu(){
}

public Stu(String id,String name,int age){
this.id=id;
this.name=name;
this.age=age;
}

public void read(){
System.out.println(name+" is reading.");
}

public static void main(String[] args) {
Stu stu = new Stu("001","john",21);
stu.read();
}
}

静态方法

静态方法可以直接调用,不需要实例化对象

1
2
3
4
5
6
7
8
9
public class Stu {
public static void staticread(){
System.out.println("reading.");
}

public static void main(String[] args) {
Stu.staticread();
}
}

方法的重载

同一个类中,允许存在一个以上的同名方法,他们的参数个数或参数顺序或参数类型或返回值类型不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Stu {
String id;
String name;
int age;

void show(int a){
System.out.println(a);
}

void show(double b,int a){
System.out.println(b);
}

int show(double b,int a,char c){
System.out.println(c);
return a;
}

public static void main(String[] args) {
Stu stu = new Stu();
int a = 10;
double b = 5.5;
char c = 'c';
stu.show(a);
stu.show(b,a);
int tmp = stu.show(b,a,c);
System.out.println(tmp);
}
}

>>>
10
5.5
c
10

封装

隐藏对象的属性和方法实现细节,仅对外公开用于操作内部数据的接口,控制程序中属性的读和修改的访问权限。

继承

提高代码复用性,继承是多态的前提。

1
2
3
class SonClass externs FatherClass{

}

子类自动拥有父类的所有属性和方法,所有类都是Object的子类。
当创建子类的时候,不管使用的子类的哪个构造器,默认情况下总会调用父类的无参构造器。

方法的重写

子类可以重写父类的属性和方法。
子类方法的名称、参数与父类完全相同。
子类方法不能缩小父类方法的访问权限。

多态

参数定义成父类类型,可以传任意子类类型的参数。

1
FatherClass object = new SonClass();

集合体系结构

整体上可以分为两类:Collection(单列集合)和Map(双列集合)。

单列集合

Collection

List系列集合:添加元素是有序、可重复、有索引的
Set系列集合:添加元素是无序、不重复、无索引的
Collection是单列集合的父接口,它的功能是全部单列集合都可以继承使用的。

方法名称 说明
public boolean add(E e) 把给定的对象添加到当前集合中
public void clear() 清空集合中所有的元素
public boolean remove(E e) 把给定的对象在当前集合中删除
public boolean contains(Object obj) 判断当前集合中是否包含给定的对象
public boolean isEmpty() 判断当前集合是否为空
public int size() 返回集合中元素的个数/集合的长度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class A01_CollectionDemo1 {
public static void main(String[] args) {
/* 注意点:
Collection是一个接口,我们不能直接创建它的对象
实现类:ArrayList
*/
Collection<String> coll = new ArrayList<>();
//1.添加元素
//细节1.如果我们往List系列集合中添加数据,那么方法永远返回true
//细节2.如果我们往Set系列集合中添加数据,如果当前要添加元素不存在,方法返回true,表示添加成功,如果要添加的元素已经存在,方法返回false
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
System.out.println(coll); //[aaa, bbb, ccc]

//2.清空
/* coll.clear();
System.out.println(coll); //[]*/

//3.删除
//细节1:因为Collection里面定义的是共性的方法,所以此时不能通过索引进行删除,只能通过元素的对象进行删除
//细节2:删除成功发回true,如果删除的元素不存在,删除失败返回false
coll.remove("aaa");
System.out.println(coll); //[bbb, ccc]

//4.判断元素是否包含
//细节:底层是依赖equals方法进行判断是否存在
//如果集合中存储是自定义对象,也想通过contains方法来判断是否包含,那么在javabean类中要重写equals方法。
boolean result=coll.contains("aaa");
System.out.println(result); //false

//5.判断集合是否为空
//底层是判断size==0
boolean result2=coll.isEmpty();
System.out.println(result2); //false

//6.获取集合的长度
int size = coll.size();
System.out.println(size); //2
}
}

size()

int size();
返回集合中的元素数量。

isEmpty()

boolean isEmpty()
如果集合不包含任何元素,返回true,否则返回false。

contains(Object o)

boolean contains(Object o)
如果集合中包含至少一个与指定对象相等的元素,返回true。

iterator()

Iterator<E> iterator();
返回一个迭代器,以便遍历集合中的元素。

add(E e)

boolean add(E e)
向集合中添加指定的元素。如果集合因操作而发生改变,则返回true(可选操作)。

remove(Object o)

boolean remove(Object o)
从集合中移除一个指定元素的单一实例(如果存在)。如果集合中包含指定元素并移除成功,则返回true(可选操作)。

containsAll(Collection<?> c)

boolean containsAll(Collection<?> c);
如果集合包含指定集合中的所有元素,返回true。

addAll(Collection<? extends E> c)

boolean addAll(Collection<? extends E> c);
将指定集合中的所有元素添加到当前集合中。

removeAll(Collection<?> c)

boolean removeAll(Collection<?> c);
从集合中移除所有也包含在指定集合中的元素。如果集合因操作而发生改变,则返回true(可选操作)。

clear();

void clear();
移除集合中的所有元素。

equals(Object o)

boolean equals(Object o);
将指定对象与集合进行比较以判断是否相等。如果指定对象与集合相等,返回true。

hashCode()

int hashCode();
返回集合的哈希码值。通常根据集合中包含的元素计算哈希码。

toArray()

3
Object[] toArray();
返回一个包含集合中所有元素的数组。

toArray(T[] a)

<T> T[] toArray(T[] a)
返回一个包含集合中所有元素的数组,其中返回数组的运行时类型与指定数组相同。

Collection的遍历方式

迭代器遍历

迭代器不依赖索引,迭代器在Java的类是Iterator,迭代器是集合专用的遍历方式。
Collection
集合获取迭代器

方法名称 说明
Iterator iterator 返回迭代器对象,默认指向当前集合的0索引

Iterator中的常用方法

方法名称 说明
boolean hasNext() 判断当前位置是否有元素
E next() 获取当前位置的元素,并将迭代器对象移向下一个位置
void remove() 从迭代器指向的collection中移除迭代器返回的最后一个元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
//获取迭代器对象
//迭代器就好比一个箭头,默认指向集合的0索引处
Iterator<String> it = coll.iterator();
//利用循环不断地获取集合中的每一个元素
while (it.hasNext()){
//next方法做的事情:获取元素并移动指针
String tmp=it.next();
System.out.println(tmp);
}
>>>
aaa
bbb
ccc
ddd

细节注意
1.报错 NoSuchElementException,循环结束,迭代器指针指向空
2.迭代器遍历完毕,指针不会复位
3.循环中只能用一次next方法
4.迭代器遍历时,不能用集合的方法进行增加或删除

增强for遍历

  • 增强for的底层就是迭代器,为了简化迭代器的代码书写的。
  • 它是JDK5之后出现的,其内部原理就是一个Iterator迭代器。
  • 所有的单列集合和数组才能用增强for进行遍历。

格式:

1
2
3
for(元素的数据类型 变量名:数组或者集合){
语句体;
}

实践

1
2
3
4
5
6
7
8
9
10
11
12
13
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
for (String s : coll) {
System.out.println(s);
}
>>>
aaa
bbb
ccc
ddd

Lambda表达式遍历

得益于JDK8开始的新技术Lambda表达式,提供了一种更简单、更直接的遍历集合的方式。

方法名称 说明
default void forEach(Consumer<? super T> action): 结合lambda遍历集合

先用匿名内部类的形式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
coll.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
>>>
aaa
bbb
ccc
ddd

lambda表达式
()->{};

1
2
3
4
5
6
7
8
9
10
11
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
coll.forEach(s-> System.out.println(s));
>>>
aaa
bbb
ccc
ddd

List

List集合的特点

  • 有序:存和取的元素顺序一致
  • 有索引:可以通过索引操作方式
  • 可重复:存储的元素可以重复

List集合的特有方法

  • Collection的方法List都继承了
  • List集合因为有索引,所以多了很多索引操作的方法
方法名称 说明
void add(int index,E element) 在集合中的指定位置插入指定的元素
E remove(int index) 删除指定索引处的元素,返回被删除的元素
E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//创建集合
List<String> list= new ArrayList<>();
//添加元素
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
//打印集合
System.out.println(list); //[aaa, bbb, ccc, ddd]
//指定位置添加元素
list.add(1,"QQQ");
System.out.println(list); //[aaa, QQQ, bbb, ccc,ddd]

//删除指定元素
String remove = list.remove(1);
System.out.println(remove); //QQQ
System.out.println(list); //[aaa, bbb, ccc, ddd]
//特殊情况
//当要删除的对象的类型和索引的类型一样时要进行装箱操作
//函数重载,优先调用实参跟形参类型一致的哪个方法
List<Integer> list= new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Integer i = Integer.valueOf(1); //装箱
list.remove(i);
System.out.println(list); //[2, 3]
String result=list.set(1,"QQQ");
System.out.println(result); //bbb
System.out.println(list); //[aaa, QQQ, ccc, ddd]
String t= list.get(1);
System.out.println(result); //bbb

List集合的遍历方式

迭代器遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
List<String> list= new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
Iterator<String> it = list.iterator();
while (it.hasNext()){
String tmp = it.next();
System.out.println(tmp);
}
>>>
aaa
bbb
ccc
ddd

增强for

1
2
3
4
5
6
7
8
9
10
11
12
13
List<String> list= new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
for(String s:list){
System.out.println(s);
}
>>>
aaa
bbb
ccc
ddd

lambda表达式
匿名内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
List<String> list= new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
>>>
aaa
bbb
ccc
ddd

lambda表达式

1
2
3
4
5
6
7
8
9
10
11
List<String> list= new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.forEach(s -> System.out.println(s));
>>>
aaa
bbb
ccc
ddd

普通for

1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<String> list= new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
for (int i = 0; i < list.size(); i++) {
String s=list.get(i);
System.out.println(s);
}
>>>
aaa
bbb
ccc
ddd

列表迭代器

获取一个列表迭代器对象,里面的指针默认也是指向0索引的

方法 说明
void add()
boolean hasNext()
E next()
int nextIndex()
boolean hasPrevious()
E previous()
int previousIndex
void remove()
1
2
3
4
5
6
7
8
9
10
11
12
List<String> list= new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
ListIterator<String> it = list.listIterator();
while (it.hasNext()){
String s = it.next();
if("bbb".equals(s)){
it.add("QQQ");
}
}

5中遍历方式对比
迭代器遍历:在遍历过程中需要删除元素,使用迭代器
列表迭代器:在遍历过程中需要添加元素,使用列表迭代器
增强for和lambda表达式:仅仅想遍历,使用增强for或lambda
普通for:想操作索引,可以用普通for

addAll(int index, Collection<? extends E> c)

boolean addAll(int index, Collection<? extends E> c);
将指定集合c中的所有元素,从指定位置index开始插入到列表中。如果插入操作成功,返回true。

retainAll(Collection<?> c);

boolean retainAll(Collection<?> c);
保留列表中那些在指定集合c中也包含的元素,删除列表中不在c中的所有元素。如果列表因为此操作发生改变,则返回true。

replaceAll

void replaceAll(UnaryOperator<E> operator);
对列表中的每个元素应用指定的operator(操作函数),并用操作后的结果替换原来的元素。

sort(Comparator<? super E> c)

void sort(Comparator<? super E> c);
根据指定的比较器c对列表进行排序。如果c为null,则使用元素的自然顺序排序。

get(int index)

E get(int index);
返回列表中指定位置index的元素。

set(int index, E element);

E set(int index, E element);
用指定的元素element替换列表中指定位置index的元素,并返回被替换的元素。

add(int index, E element)

void add(int index, E element);
在列表中指定的位置index插入指定的元素element。原位置及之后的元素将向右移动一位。

remove(int index);

E remove(int index);
移除列表中指定位置index的元素,并返回被移除的元素。后续的元素向左移动一位。

indexOf(Object o)

int indexOf(Object o);
返回列表中首次出现指定元素o的索引位置,如果列表中不包含该元素,则返回-1。

lastIndexOf(Object o)

int lastIndexOf(Object o);
返回列表中最后一次出现指定元素o的索引位置,如果列表中不包含该元素,则返回-1。

subList(int fromIndex, int toIndex)

List<E> subList(int fromIndex, int toIndex);
返回列表中从fromIndex(包含)到toIndex(不包含)之间的部分视图。返回的子列表是原列表的视图,因此对子列表的更改会反映到原列表中,反之亦然。

listIterator()

ListIterator<E> listIterator();
返回一个列表迭代器(ListIterator),用于遍历List中的元素。

ArrayList

数组创建过程

1
ArrayList arrays = new ArrayList();
1
2
3
4
5
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

数组扩容机制

  • 使用无参构造,创建ArrayList对象时,初始elementData容量为0,第一次添加,扩容elementData容量为10,如需再次扩容,则扩容elementData的容量为原来的1.5倍。
  • 使用有参构造,初始elementData容量为指定大小,如需扩容,则直接扩大为elementData原来容量的1.5倍。

Vector

Vector与ArrayList基本相同,Vector线程安全,ArrayList执行效率高
Vector扩容机制

  • 使用无参构造,创建Vector对象时,初始elementData容量为10,如需再次扩容,则扩容为原来的两倍
  • 使用指定大小的构造器,初始容量为指定大小,如需再次扩容,则扩容为原来的两倍
  • 也可以自己指定每次扩容个数

LinkedList

  • LinkedList底层是一个双向链表
  • LinkedList中有两个属性first和last分别指向首节点和尾节点
  • 每个节点里面又有prev、next、item三个属性,其中item中存放元素,prev指向前一个节点,next指向后一个节点,实现双向链表

属性

first
transient Node<E> first;
last
transient Node<E> last;

getFirst()

public E getFirst()

getLast()

public E getLast()

removeFirst()

public E removeFirst()

removeLast()

public E removeLast()

addFirst(E e)

public void addFirst(E e)

addLast(E e)

public void addLast(E e)

Set

  • 无序,没有索引
  • 取出的顺序不是添加的顺序,但是取出的顺序固定
  • 不允许重复元素,最多包含一个null

HashSet

Java中的HashSet是一个实现了Set接口的集合类,HashSet的实现基于HashMap。

数据结构(栈、队列、数组、链表)

栈的特点:后进先出,先进后出

队列

队列的特点:先进先出,后进后出

数组

  • 查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中连续存储) 。
  • 删除效率低:要将原始数据删除,同时后面每个数据前移。
  • 添加效率极低:添加位置后的每个数据后移,再添加元素。

链表

结点

在链表中第一个创建的节点是头节点
链表的特点
查询慢,增删快

ArrayList

ArrayList底层是数组结构

1
2
3
4
5
6
7
8
9
10
ArrayList<String> list1=new ArrayList<>();
//一次添加一个元素
list1.add("aaa");
list1.add("bbb");
list1.add("ccc");
//一次添加多个元素
ArrayList<String> list2=new ArrayList<>();
list2.addAll(list1);

System.out.println(list2); //[aaa, bbb, ccc]

ArrayList集合底层原理

  • 利用空参创建的集合,在底层创建一个默认长度为0的数组(名为elementData,size为0)
  • 添加第一个元素时,底层会创建一个新的长度为10的数组
  • 存满时,会扩容1.5倍
  • 如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际长度为准

查源码,打开IDEA,按Ctrl+N,输入类名

查看大纲,按下ALT+7Ctrl+F12

源码分析

泛型

  泛型的本质是为了将类型参数化,也就是说在泛型使用过程中,数据类型被设置为一个参数,在使用时再从外部传入一个数据类型;而一旦传入了具体的数据类型后,传入变量(实参)的数据类型如果不匹配,编译器就会直接报错。

使用泛型代码

1
2
3
4
5
6
7
8
9
public static void test(){
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
for (String string : list) {
System.out.println(string);
}
}

自定义泛型类

1
2
3
4
5
6
7
8
9
10
11
class people<E> {
public E name;
public void test(){
System.out.println(name);
}
}

public static void main(String[] args) {
People<String> people = new People<>();
people.name = "bailetian";
System.out.println(people.name);

泛型方法

1
2
3
public static <T> void test(T x){
System.out.println(x);
}

泛型通配符

  • :被称作无限定的通配符。
  • :被称作有上界的通配符。
  • :被称作有下界的通配符。

反射

反射允许对封装类的字段、方法和构造函数进行编程访问。

获取class对象的三种方式

  • Class.forName(“全类名”);
    源代码阶段(A.java和A.class)
  • 类名.class;
    加载阶段(内存中A.class)
  • 对象.getClass();
    运行阶段(内存中创建对象)
1
2
3
4
5
6
package com.demo.myfelect;

public class Student {
public String name;
public int age;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.demo.myfelect;

public class myreflect {
public static void main(String[] args) throws ClassNotFoundException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Class cls2 = Student.class;
System.out.println(cls2);

Student stu = new Student();
Class cls3 = stu.getClass();
System.out.println(cls3);
}
}

利用反射获取构造方法

  • Constructor<?>[] getConstructors()
    返回所有公共构造方法对象的数组
  • Constructor<?>[] getDeclaredConstructors()
    返回所有构造方法对象的数组
  • Constructor getConstructor(Class<?>…parameterTypes)
    返回单个公共构造方法对象
  • Constructor getDeclaredConstructor(Class<?>…parameterTypes)
    返回单个构造方法对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.demo.myfelect;

public class Student {
public String name;
public int age;

public Student() {
}

public Student(String name) {
this.name = name;
}

protected Student(int age) {
this.age = age;
}

private Student(String name, int age) {
this.name = name;
this.age = age;
}
}

getConstructors()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Constructor[] constructors=cls1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
}

>>>
class com.demo.myfelect.Student
public com.demo.myfelect.Student(java.lang.String)
public com.demo.myfelect.Student()

getDeclaredConstructors()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Constructor[] constructors=cls1.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
}

>>>
class com.demo.myfelect.Student
protected com.demo.myfelect.Student(java.lang.String,int)
private com.demo.myfelect.Student(int)
public com.demo.myfelect.Student(java.lang.String)
public com.demo.myfelect.Student()

getConstructor(Class<?>…parameterTypes)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Constructor constructor=cls1.getConstructor(String.class);
System.out.println(constructor);

}
}

>>>
class com.demo.myfelect.Student
public com.demo.myfelect.Student(java.lang.String)

getDeclaredConstructor(Class<?>…parameterTypes)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);


Constructor cons=cls1.getDeclaredConstructor(int.class);
System.out.println(cons);
}
}

>>>
class com.demo.myfelect.Student
private com.demo.myfelect.Student(int)

getModifiers()

  • 获取成员(类、方法、构造器或字段)的修饰符。

getParameters()

  • 获取方法的参数信息。
  • 这个方法返回一个 Parameter[] 数组,每个 Parameter 对象代表方法的一个参数。

setAccessible(true)

临时取消权限校验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);


Constructor cons=cls1.getDeclaredConstructor(int.class);
System.out.println(cons);

cons.setAccessible(true);
Student stu = (Student) cons.newInstance(21);
System.out.println(stu.age);
}
}

>>>
class com.demo.myfelect.Student
private com.demo.myfelect.Student(int)
21

利用反射获取成员变量

  • Field[] getFields()
    返回所有公共成员变量对象的数组
  • Field[] getDeclaredFields()
    返回所有成员变量的数组
  • Field[] getField(String name)
    返回单个公共成员变量对象
  • Field[] getDeclaredField(String name)
    返回单个成员变量对象
1
2
3
4
5
public class Student {
public String name;
protected int age;
private String genda;
}

getFields()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Field[] fields = cls1.getFields();
for (Field field : fields) {
System.out.println(field);
}
}
}

>>>
class com.demo.myfelect.Student
public java.lang.String com.demo.myfelect.Student.name

getDeclaredFields()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Field[] fields = cls1.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
}
}

>>>
class com.demo.myfelect.Student
public java.lang.String com.demo.myfelect.Student.name
protected int com.demo.myfelect.Student.age
private java.lang.String com.demo.myfelect.Student.genda

getField(String name)

1
2
3
4
5
6
7
8
9
10
11
12
13
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Field fields = cls1.getField("name");
System.out.println(fields);
}
}

>>>
class com.demo.myfelect.Student
public java.lang.String com.demo.myfelect.Student.name

getDeclaredField(String name)

1
2
3
4
5
6
7
8
9
10
11
12
13
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Field fields = cls1.getDeclaredField("genda");
System.out.println(fields);
}
}

>>>
class com.demo.myfelect.Student
private java.lang.String com.demo.myfelect.Student.genda

getName()

获取各种对象的名称

getType()

获取字段或参数的类型

get()

获取字段的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Field fename = cls1.getField("name");

Student stu = new Student();
stu.name = "Bailetian";
String value = (String) fename.get(stu);
System.out.println(value);

}
}

>>>
class com.demo.myfelect.Student
Bailetian

set()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Field fename = cls1.getField("name");

Student stu = new Student();
stu.name = "Bailetian";

fename.set(stu,"bblltt");
System.out.println(stu.name);

}
}

>>>
class com.demo.myfelect.Student
bblltt

利用反射获取成员方法

  • Method[] getMethods()
    返回所有公共成员方法对象的数组,包括继承的
  • Method[] getDeclaredMethods()
    返回所有成员方法对象的数组,不包括继承的
  • Method getMethod(String name,Class<?>…parameterTypes)
    返回单个公共成员方法对象
  • Method getDeclaredMethod(String name,Class<?>…parameterTypes)
    返回单个成员方法对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Student {
public String name;
protected int age;
private String genda;

public Student() {
}

public Student(String name, int age, String genda) {
this.name = name;
this.age = age;
this.genda = genda;
}

public void test(){
System.out.println("this is a method test!!");
}

public void testname(String name){
System.out.println("the name is :"+name);
}
}

getMethods()

1
2
3
4
5
6
7
8
9
10
11
12
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Method[] methods = cls1.getMethods();
for (Method method : methods) {
System.out.println(method);
}

}
}

getDeclaredMethods()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Method[] methods = cls1.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
}
}

>>>
class com.demo.myfelect.Student
public void com.demo.myfelect.Student.testname(java.lang.String)
public void com.demo.myfelect.Student.test()

getMethod(String name,Class<?>…parameterTypes)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Method method = cls1.getMethod("test");
System.out.println(method);

}
}

>>>
class com.demo.myfelect.Student
public void com.demo.myfelect.Student.test()

getDeclaredMethod(String name,Class<?>…parameterTypes)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Method method = cls1.getDeclaredMethod("testname",String.class);
System.out.println(method);

}
}

>>>
class com.demo.myfelect.Student
public void com.demo.myfelect.Student.testname(java.lang.String)

invoke(Object object…args)

调用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class myreflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class cls1 = Class.forName("com.demo.myfelect.Student");
System.out.println(cls1);

Method method = cls1.getDeclaredMethod("testname",String.class);
System.out.println(method);

Student stu = new Student("blt",21,"male");

method.invoke(stu,"blt");
}
}

>>>
class com.demo.myfelect.Student
public void com.demo.myfelect.Student.testname(java.lang.String)
the name is :blt