banner
NEWS LETTER

Java SE笔记

Scroll down

Java基础

Java入门

Java概述

Java是由sun公司在1996年正式发布的高级编程语言。JAVA语言的诞生解决了网络程序的安全、健壮、平台无关、可移植等很多难题。

Java技术平台简介

Java SE:标准版

  1. Java技术的基础和核心

  2. 主要用于开发桌面应用程序

Java EE:企业版

  1. 提供了企业级的应用开发的完整解决方案

  2. 很多的网站都是采用Java EE技术开发

Java环境搭建

详情见:Java 开发环境配置 | 菜鸟教程 (runoob.com)

基本结构

1
2
3
4
5
6
7
8
9
10
11
public class aba{

    public static void main(String [] args){

//main()方法是java程序的入口点

        System.out.println("Hello World!!!");

    }

}

转义符

\n 将光标移动到下一行的第一格

\t 将光标移到下一个水平制表位置(加制表符)

注释

单行注释以//开始

多行注释以/* */框起来

Java编码规范

  1. 类名使用public修饰

  2. 一行只写一句语句

  3. 每一条Java语句必须以分号结束

  4. { }的使用及位置

  5. 代码缩进

Java输入输出

  1. 输入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Scanner input =new Scanner(System.in);

        double aaa =input.next(); 获取键盘输入的值

.nextInt(); 用于获取整形数

                         .nextDouble() 用于获取小数

                         .nextChar() 用于获取字符

                         .nextBoolean() 用于获取布朗值

.nextLine() 获取键盘输入的值

next()和nextLine()的区别

next():

  1. 一定要读取到有效字符后才能结束输入

  2. 对输入有效字符之前遇到的空白,next()方法会自动将其去掉

  3. 只有输入有效字符后才能将其后面输入的空白作为分隔符或者结束符

  4. next()不能得到带有空格的字符串

nextLine():

  1. 以enter为结束符,也就是说nextLine()方法返回的是输入回车之前 的所有字符

  2. 可以获得空白

 

  1. 输出
1
System.out.print(" ")

数据类型和运算符

常用的数据类型

数据类型 说明 默认值
byte() 是8位、有符号的,以二进制补码表示的整数 0
char(字符型) 用于存储单个字符 ‘u0000’
int(整型) 用于存储整数二进制以00开头,八进制以0开头,十六进制以0x开头 0
double(双精度) 用于存储小数 0.0d
String(字符串) 用于存储一串字符 null
long() 存储int盛不下的整数 0L
Short(短整型) 整形的一种 0
boolean(布尔值) 判别真假,数据类型表示一位的信息 false

自动类型转换规则:

规则一:如果一个操作数为double型,则整个表达式可提升为double型

规则二:两个类型要兼容,数值类型(整型和浮点型)相互兼容

目标类型大于源类型,例如double型>float型 >long型>int型>byte、short、char

强制类型转换:

例如:double a=10.24

Int b=(int)a

注:1.byte、short、char这三种类型都可以发生数学运算(char中的字母会默认变成ascll码处理)

2.小的单位在运算的时候都会被首先提升成为大类型然后在计算

数据类型除了八种基本数据类型还会有三种引用类型

类(class), 接口(interface),数组(array),(枚举类型、注解类型、字符串(String)类型) 

运算符

  1. 赋值运算符:=、+=、-=、*=、/=、%=

  2. 算术运算符:+、-、*、/、%、num1++等价于num1=num1+1、–同上

  3. 关系运算符:>、<、==、!=、>=、<=

  4. 逻辑运算符:&&与、||或、!非

运算符的优先级:小括号>算术运算符>关系运算符>逻辑运算符>赋值运算符

  1. 位运算符:
运算符 描述
& 如果相对应的位数都是1,则返回1,否则返回0
| 如果相对应的位数都是0,则返回0,否则返回1
^ 如果对应位置的位数相同则返回0,如果不同则返回1
~ 按位取反,-1在取反
<< 左移,左移一位相当于*2
>> 右移,右移一位相当于除以2取商
>>> 右移指定位数前面补零
  1. instanceof运算符

使用格式:

1
2
String name = "James";
boolean result = name instanceof String; // 由于 name 是 String 类型,所以返回真
  1. 条件运算符

条件运算符也被称为三元运算符。该运算符有3个操作数,并且需要判断布尔表达式的值。该运算符的主要是决定哪个值应该赋值给变量。

例如:

1
2
3
4
5
6
7
int a=10;

int b;

b=(a<5) ? 6:9;

System.out.println(b); //b=9

选择结构

if选择结构

1
2
3
4
5
if(条件){
//如果满足条件返回的代码块
}else{
//如果不满足条件返回的代码块
}

多重if选择结构

1
2
3
4
5
6
7
if(条件1){

}else if(条件2){

}else{

}

switch选择结构

1
2
3
4
5
6
7
8
9
10
11
12
switch(表达式){
case 常量1;
语句;
break;
case 常量2;
语句;
break;
...
default;
语句;
break;
}

switch后边的控制表达式的数据类型只能是整数和字符型,不能是boolean型

switch和多重if选择结构:

相同点:都用来处理多分支条件的结构

不同点:switch只能处理等值条件判断的情况,而且条件必须是整形或字符型变量

多重if选择结构适合某个变量处于某个连续区间时的情况

循环结构

for循环

1
2
3
4
5
6
forint i=0;i&lt;=100;i++){
//初始化参数 条件判断 迭代
System.out.println(“好好学习!”)
break; //结束这个循环
countinue;//跳出这次循环执行下一次
}

while循环

1
2
3
4
while(i&lt;=100) { //循环条件
System.out.println(""); //执行代码块
i++; //迭代
}

do-while循环

1
2
3
4
5
6
7
8
9
10
do{

循环操作

}while(循环条件)

/*注:while和do-while的区别
执行次序不同:while先判断在执行,do-while先执行后判断
初次情况不满足循环条件时:while一次都不执行
do-while不管任何情况都会执行一次*/

break和continue

break用于完全结束一个循环,跳出循环体

break不仅可以结束其所在的循环,还可以直接结束其外部循环。此时需要在break后紧跟一个标签,这个标签用于表示一个外层循环

详情见带标签的break语句

continue用于在循环体中结束本次循环,开始下一次循环

递归结构

递归结构的思想就是自己调用自己

递归结构两个部分:

定义递归头:什么时候不调用方法。如果没有头将陷入死循环,也就是结束条件

递归体:什么时候要调用自身方法

数组

什么是数组

数组是一个变量存储相同数据类型的一组数据

数组基本要素

标识符:数组的名称,用于区别不同的数组

数组元素:向数组中存放的数据

元素下标:对数组元素进行编号

元素类型:数组元素的数据类型(数组中的所有元素必须属于相同的数据类型)

注:数组长度固定不变,避免数组越界

使用数组四步走

  1. 声明数组:int a[ ];(声明数组时不规定数组长度)

  2. 分配空间:a=new int[5];

数据类型[ ] 数组名 = new 数组类型[大小]

  1. 赋值: a[0]=8;
  • 方法一:边声明边赋值

int score[ ]={89,79,76};

int score[ ]=new int[ ]{89,79,76}; //不能指定数组长度

  • 方法二:动态从键盘中获取信息并赋值
1
2
3
4
5
Scanner input = new Scanner(System.in);

for(int I =0;i&lt;30;i++){
score[i]=input.nextlnt();
}
  1. 处理数据:a[0]=a[0]*10

For-Each循环

在不使用索引的情况下输出所有数组元素

1
2
3
for(数组类型 element:数组名){
System.out.print(element);
}

数组方法

  1. 将数组转化成长度固定的列表(Arrays.asList)
1
2
List<String> list1 = Arrays.asList(数组名);
System.out.println(list1);

变量

成员变量和局部变量的区别

  • 作用域不同

    • 局部变量的作用域仅限于定义它的方法

    • 成员变量的作用域在整个类内部都是可见的

  • 初始值不同

    • Java会给成员变量一个初始值

    • Java不会给局部变量初始值

局部变量包括:方法体、代码块、形参

注:在同一个方法中,不允许有同名局部变量;在不同的方法中,可以有同名局部变量。

在同一个类中,成员变量和局部变量同名时,局部变量具有更高的优先性

Final修饰符

在JAVA语言中,用关键字final来定义一个常量

常量一旦被初始化后就不能改变

声明格式:

1
final 数据类型 名称=内容;

final

final关键字可以用于修饰类、变量和方法

final修饰变量:

final修饰的类变量和方法不能改变

final修饰的变量(常量),必须要赋初始值

final可以 在创建时赋值,可以在普通初始化代码块中,可以在构造方法中

final创建的类变量,只能在创建时赋值和在静态初始化代码中

final修饰方法:

如果用final修饰方法,如果有子类那么不能在子类中重写此方法

final修饰类:

final修饰类则此类不可派生子类

方法(函数)

方法概述

就是将一个功能抽取出来,把代码单独定义在一个大括号内形成一个独立的包装。当我们需要这个功能的时候,就可以去调用,这样既实现了代码的复用性,也解决了代码冗余的现象

定义的格式

例如:

1
2
3
4
5
6
7
8
9
10
public class score {
public static void main(String[] args) {
System.out.println(aaa(10,20));
}

public static int aaa(int a,int b) {
int ret=a+b;
return ret;
}
}

方法定义的注意事项

方法定义的先后顺序无所谓

方法定义必须是挨着的,不能在一个方法的内部定义另一个方法

方法定义之后自己不会执行,如果希望执行,一定要进行方法的调用

方法的返回值

返回值类型分为:基本数据类型和引用数据类型

基本数据类型return的值必须和数据类型一致

引用数据类型:

为类时return该类的对象

为抽象类名时return该类的子类对象

为接口名时return该接口的实现类的对象

类和对象

什么是类

整个程序的基本单位就是类,方法是从属于类和对象

Java是面向对象的语言

  1. 所有的Java程序都是以类class为组织单元

  2. 关键字class定义自定义的数据类型

创建类

类的方法示例

public 返回值类型 方法名(){

​ //这里编写方法的主体

}

方法的返回值

  • 如果方法具有返回值,方法中必须使用关键字return返回该值,返回值为该返回值的类型

  • 如果方法没有返回值,返回值类型为void

注:一个文件中可以有多个类,但是公共的类只能有一个,就是public修饰的那一个,每存在一个类运行时系统就会自行创建一个class文件

创建对象

初始化块

初始化块分为:普通初始化块和静态初始化块

普通初始化和静态初始化的区别:

  1. 定义格式不同:普通初始化直接用{ }引起来,静态初始化要在前面加上static

  2. 初始化对象不同:普通初始化块为对象进行初始化,静态初始化为类进行初始化

  3. 调用方法不同: 普通初始化在创建对象时隐式调用,静态初始化在类加载时隐式调用

  4. 调用次数不同:静态初始化可以多次被调用随着对象的创建进行添加,静态初始化只能被调用一次

初始化对象执行顺序:

静态初始化>普通初始化>构造方法

有子类初始化对象执行顺序:

父类静态初始化>子类静态初始化>父类普通初始化>父类构造方法>子类普通初始化>子类构造方法

构造方法用于初始化对象而静态初始化块用于初始化类

构造器

什么是构造器

用于对象的初始化,而不是创建对象

声明格式

1
2
3
4
5
[修饰符] 类名(形参列表){  
//n条语句
}

构造器四个要点
  1. 构造器通过new关键字调用

  2. 构造器不能定义返回值类型,不能使用return返回某个值

  3. 如果我们没有定义构造器,则编译器会自动定义一个无参的构造方法

  4. 构造器的方法名必须和类名一致

java虚拟机概念

java虚拟机的内存可以分成三个区域:栈stack、堆heep、方法区method

内存图

栈的特点

  1. 描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧

  2. jvm为每个线程创建一个帧,用来存放执行方法信息

  3. 栈属于线程私有,不能实现线程的共享

  4. 栈的存储特性是“先进后出”,“后来居上”

  5. 栈有系统自动分配速度快(栈是一个连续的内存空间)

堆的特点

  1. 用于存储创建好的对象和数组(数组也是对象)

  2. jvm只有一个堆,对接所有线程共享

  3. 是一个不连续内存空间,分配灵活速度慢

  4. 堆被所有线程共享,和堆上的区域,会被垃圾回收器做进一步划分

方法区(也是一个堆)的特点

  1. 方法区是Java虚拟机规范,可以有不同的实现

  2. jvm只有一个方法区,被所有线程共享

  3. 方法区实际也是堆,只是用于存储类、常量相关的信息

  4. 用来存放程序中哟永远不变或者唯一的内容(类信息、静态信息、字符串信息)

  5. 常量池存放常量:如文本字符串、final常量

访问权限修饰符

private friendly(默认) protected public
当前类访问权限
包访问权限 ×
子类访问权限 × ×
其他类访问权限 × × ×

构造方法

构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时其实就是在调用结构方法

格式:

1
2
3
public 类名称(参数类型 参数名称){
方法名
}

注意事项:

  1. 构造方法的名称必须和所在的类名完全一样,就连大小写也是一样

  2. 构造方法不能写返回类型,连void都不写

  3. 构造方法不能return一个具体的返回值

  4. 如果没有编写任何构造方法,那么编译器将会默认赠送一个构造方法,没有参数,方法体什么事情都不做

  5. 一旦编写了至少一个构造方法,那么编译器将不再赠送

  6. 构造方法也是可以进行重载的

重载:方法名称相同,参数列表不同

面向对象三大特性

封装在java中的体现(增强安全性和简化编程)

  1. 方法就是一种封装

  2. 关键字private也是一种封装

    1. 一旦使用了private进行修饰,那么本类当中仍然可以随意访问,但是超出了本类的范围之外就不能直接访问了

但是可以间接访问private成员变量,就是定义一对Getter和Setter方法

使用规则:

必须叫setXxx或者是getXxx的命名规则

对于Getter来说,不能有参数,返回值类型和成员变量对应

对于Setter来说,不能有返回值,参数类型和成员变量对应

封装就是将一些细节隐藏起来对外界不可见

java中的继承性(解决代码可复用性)

在继承的关系中,“子类就是一个父类”。也就是说,子类可以被当做父类看待

定义父类的格式

1
2
3
public class 父类名称{

}

定义子类的格式

1
2
3
public class 子类名称 extends 父类名称{

}

注:子类在引用时可以找到父类中的方法和变量,但是父类就只能调用自己的

super详解:

  1. super是Java的关键字,他是直接父类对象的引用

  2. 就像this不能出现在static修饰的方法中一样,super也不能出现在static修饰的方法中

  3. 如果子类定义里父类同名的属性,也会发生子类属性覆盖父类属性的情形。子类的方法直接访问该属性,都会访问到覆盖属性,无法访问父类被覆盖的属性—通过super访问父类被覆盖的属性

  4. 如果没有在子类中写super,系统将会自动调用

  5. 一般把super写到方法的最前面

在继承中,当父类有构造方法时,子类一定会调用父类的构造方法

java中的多态(增加程序可扩充性)

多态就是:父类引用指向子类对象

父类名称 对象名=new 子类名称()

多态只能调用子类和父类都有的方法

如果非要调用子类自己有的方法就需要

向上转型:

Animal an1=new Dog();

a1.sleep(); //报错的 原因:an1是父类对象,父类没有办法调用子类

Dog d=(Dog)an1; 这实际上就是将父类当做子类使用,也叫作向上转型

d.sleep(); //正确的

抽象方法和抽象类

什么是抽象方法和抽象类

抽象方法:就是在方法的基础上加上abstract关键字,然后去掉大括号,直接分号结束

抽象类:就是抽象方法所在的类,必须是抽象类才行,在class前面加上abstract即可

使用抽象方法和抽象类的注意事项

  1. 不能直接new抽象类对象,必须用一个子类来继承抽象父类

  2. 子类必须覆盖重写抽象父类的所有的抽象方法

重写和覆盖的实现:子类去掉抽象方法的abstract关键字,然后补上方法的大括号

  1. 创建子类对象进行使用

  2. 在抽象类中,不一定包含抽象对象,但是有抽象方法的类必须是抽象类

abstract使用注意事项

  1. final和abstract永远不能同时使用

  2. abstract不能修饰变量

  3. static和abstract也不能同时使用

  4. private和abstract也不能同时使用

this关键字的使用

当方法的局部变量和成员变量重名是,根据就近原则会优先赋局部变量的值。如果想要使用成员变量的值就要用到this.成员变量名

this案例

对象数组的声明和使用

初始化变量

类名称 [ ]对象数组名=new 类名称[ ]{对象,对象……}

ArrayList类

什么是ArrayList类

ArrayList是大小可变数组的实现,存储在内的东西叫元素,ArrayList可以无限往里添加元素,大小也会随着元素的变化而变化

创建

ArrayList<String> zu=new ArrayList<>();

ArrayList后面有一个<E>代表泛值

泛值:也就是装在集合中的所有元素,全都是统一的什么类型

注意,泛值只能是引用类型,不能是基本类型

注意事项:

对于ArrayList集合来说,可以直接打印内容

如果内容为空,得到的是空的中括号

ArrayList添加、访问、删除和获取长度

1
2
3
4
5
6
7
8
9
10
11
12
13
添加:zu.add(“嗨害嗨”);

public boolean add(E e)
注意事项:添加的数据类型要符合泛值类型

访问:zu.get(0);
返回的是指定索引位置的值,

删除:zu.remove(0)
返回的是指定索引值所删除的值

访问长度:zu.size();
返回的是数组列表的长度

向ArrayList中添加基本数据类型

格式如下:

1
2
3
4
5
6
7
8
ArrayList<Integer> aaa=new ArrayList<>();
Byte
Short
Long
Float
Double
Character
Boolean

Math类

Math.abs(a)//返回a的绝对值

Math.ceil(a)//上舍入

Math.floor(a)//下舍入

Math.round(a)//四舍五入

字符串概述

什么是字符串

在程序中,但凡是使用双引号引起来的东西就是字符串

字符串的特点

  1. 字符串的内容是不可变的

  2. 正是因为字符串的内容不可变,所以字符串是可以共享使用的

  3. 字符串的效果上相当于是char[ ]字符数组,但底层原理是byte[ ]字节数组

创建字符串三种方法

1
2
3
4
5
6
7
8
9
10
11
12
13
//通过构造创建字符串对象

String name1=new String("害");
System.out.println(name1);

//根据字符数组创建字符串
char []name2={'a','b','c'};
String str1=new String(name2);
System.out.println(str1);

//根据字节数组创建字符串
byte []name3={97,98,99};
String str2=new String(name3);

System.out.println(str2);

字符串常量池

在程序当中,直接写在双引号中的字符串都是放在常量池当中

对于基本类型来讲“==”是对数值进行比较

对于引用类型来讲“==”是对地址值进行比较

字符串内容比较

.equals() //比较字符串内容(区分大小写)

.equalsIgnoreCase() //比较字符串内容(不区分大小写)

注意事项:

  1. 任何对象都可以用object接收

  2. .equals有对称性,就是说a.equals(b)和b.equals(a)效果一样

  3. 如果比较的双方一个是常量一个是变量,推荐把常量写在前面

字符串的获取

.length() //获取字符串长度

str1.concat(str2) //字符串拼接

str1.charAt(1) //获取指定位置的字符

str1.indexOf(“aaa”) //返回指定字符第一次出现位置的值,如果没有返回-1

字符串的截取

str1.substring(3) //使用一个参数是从指定字符开始截到末尾

str1.substring(3,5) //使用两个参数是从指定位置开始截到第二个参数位不包括最后一位

字符串的转化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
char []aaa= {'a','b','c','d','e','f','g'};

String zu=new String(aaa);

//字符串转化为字符数组
char [] charArray=zu.toCharArray();
System.out.println(charArray[0]); //a
System.out.println("===========");

//字符串转化为字节数组
byte [] byteArray=zu.getBytes();
System.out.println(byteArray[0]); //97
System.out.println("===========");

//字符串替换
String str1="这里是一段字符串";
String str2=str1.replace("是","\*");

//第一个参数表示要替换的字符,第二个表示替换成什么
System.out.println(str2); //这里\*一段字符串

字符串分割

//字符串分割

1
2
3
String str3="aaa,bbb,ccc,ddd";  
String [] str4=str3.split(","); //用什么分割
System.out.println(str4[0]);

接口

什么是接口

接口就是多个类的公共规则

可以通过接口来实现多重继承

接口是一种引用数据类型,最重要的内容就是其中的抽象方法

如何定义一个接口

格式:

1
2
3
public interface 接口名称{

}

接口包含的内容

java7.0可以包含

1. 常量

2. 抽象方法

java8.0额外包括

1. 默认方法

2. 静态方法

java9.0额外包括

1. 私有方法

注意:接口中只能是抽象方法,不能是其他方法

接口的定义和使用

1
2
3
4
5
6
7
8
9
10
11
public interface TestInterface {
public abstract void test(); //必须是抽象方法
}

//在实现类中必须重写接口中的抽象方法

public class extendsClass implements TestInterface{
public void test(){
System.out.println("我是从接口中重写的抽象方法");
}
}

接口的默认方法使用

1
2
3
4
5
6
7
8
public interface TestInterface {

public abstract void test();

public default void text(){

} //接口的默认方法
}

接口的默认对象可以被实现类继承和重写

接口的默认对象不需要在实现类中实现

用于解决接口的升级问题

接口中的静态方法使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface MyInterfaceStatic {

public static void methodStatic(){
System.out.println("这是接口的静态方法");
}
}

public class MyInterfaceStaticTest{
public static void main(String[] args) {
MyInterfaceStatic.methodStatic();
}
}

//接口中的静态方法可以直接在测试类中调用,因为静态方法从属于类

接口中的私有方法

可以解决的问题:

我们需要抽取一个共有的方法,用来解决两个默认方法之间重复的代码的问题。但是这个共有方法不应该让实现类使用,应该是私有化的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public interface MyInterfaceStatic {
public static void methodStatic1(){
System.out.println("静态方法1");
selectStatic();
}
public static void methodStatic2(){
System.out.println("静态方法2");
selectStatic();
}
private static void selectStatic(){
System.out.println("aaa");
System.out.println("bbb");
System.out.println("ccc");
}
}

public class MyInterfaceStaticTest{
public static void main(String[] args) {
MyInterfaceStatic.methodStatic1();
MyInterfaceStatic.methodStatic2();
}
}

内部类

内部类格式

1
2
3
4
5
6
public class MyWindow{ //外部类
String name;
public class MyEvent{ //内部类

}
}

内部类可以使用外部类中的属性和方法

创建内部类对象格式

外部类名.内部类名 对象名 =new 外部类名().new内部类名();

匿名内部类

什么是匿名内部类?

​ 就是一个没有名字的局部内部类

匿名内部类的目的是简化代码,也是开发常用的形式

匿名内部类的格式

1
2
3
4
5
new 类名|抽象类|接口(形参){

方法重写

}

匿名内部类的特点:

  1. 匿名内部类是一个没有名字的内部类

  2. 匿名内部类一旦写出来,就会立即创建一个匿名内部类的方法返回

  3. 匿名内部类的对象的类型相当于是当前new的那个的类型的子类类型

java高级编程

Java类

Random类

Random r=new Random();

Int i=r.nextInt(100);

ArrayList类

是大小可变的数组

Object类(所有的类都默认继承object)

toString方法(使用的话一般需要重写)

public String toString();返回一个字符串

equals方法

Calendar类

  • 用来获取日历
1
2
3
4
5
6
7
8
//获得一个日历
Calendar cal=Calendar.getInstance();

//获取年份
int year=cal.get(cal.YEAR);

//获取月份用0-11来表示
int month=cal.get(cal.MONTH);

  • 设置年份
1
2
3
4
5
6
7
8
//设置年份
cal.set(alendar.YEAR,2020)

//从日历的基础上增加或者减去
public abstract void add(int field,int )

//将年份减去三
cal.add(cal.YEAR,-3)

System类

  • 返回当前时间的毫秒值

System.currentTimeMillis()

  • 将数组中指定的数据拷贝到另一个数组中
1
2
3
4
5
6
7
System.arraycopy()

int [] src=new int{1,2,3,4,5};

int [] dest={6,7,8,9,10};

System.arraycopy(src,0,dest,1,3)

StringBuilder类

向字符串追加内容

toString方法,将StringBuilder类转化为String类

封装类

像int,double,long等基本数据类型是不能想引用数据类型那样调用方法的

Collection集合

集合与数组的区别:数组长度是固定的,集合长度可变;数组中存储的是同一类型数据,统一集合中可以存储多种数据类型,包括基本数据类型和引用数据类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
创建集合:

Collection<String> coll=new ArrayList<String>()

常用方法:
//将给定的对象添加到当前集合中
public boolean add();

//清空集合中所有元素
public void clear();

//把给定的对象从当前集合中删除
public boolean remove();

//判断集合中是否存在指定元素
public boolean contains(Object o);

//判断集合是否为空
boolean isEmpty();

//集合的长度,也就是集合中元素的长度
int size();

迭代器Iterator

增强for:

List

collection的子接口,不但继承了Collection接口中的全部方法

创建list:

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
List<String> list1=new ArrayList<String>();

list1.add(“alice”);

list的子类:ArrayList

list的子类:LinkedList

LinkedList<String> kdt=new LinkedList<>;();

.addFirst()添加元素到列表头部

.addLast()添加元素到列表尾部

.getFist()返回列表的第一个元素

.getLast()返回列表的最后一个元素

.removeFirst()移除并返回列表的第一个元素

.removeLast()移除并返回列表的最后一个元素

.push()向列表推入一个元素(从前面推进去)

.pop()弹出一个元素

set类

同样是继承于Collection接口,set中所存储的元素是不重复的,并且元素是无序的

  1. HashSet

HashSet的子类LinkedHashList类

查找速度快数据是有序的

Collections

往集合中添加一些元素

Collections.addAll(list,1,2,3,4,5)

打乱集合顺序

Collections.shuffle(list)

将集合中元素排序(默认升序)

Collections.sort(list)

Map(键值对)

与Collection不同,Collection当中的集合都是孤立的,向集合中存储元素都是一个个元素存储,Map中的元素都是成对存在的,每个元素都是值和键两部分组成,通过键可以找到对应的值

常用的子类中有HashMap,和HashMap下还有一个子类LinkedHashMap

常用的方法:

1
2
3
4
5
6
7
8
9
10
11
HashMap<String,String> map=new HashMap<String,String>();
//把指定的键于指定的值添加到map集合中
map.put( “218307035”,”张三”);
//移除指定的键所对应的键值对,并返回键值对的值
map.remove(“218307035”);
//获取这个键所对应的值
map.get(“218307035”);
//获取集合中所有的键
map.keySet();
//判断集合中是否包含指定的键
map.containskey(“218307035”);

遍历所有键值对

1
2
3
4
for(String key:map.keySet()){
String v=map.get(key)
System.out.println(key+”:”+v)
}

获取所有的项(键值对)

1
2
3
set<String,String> entrySet=map.entrySet();
getkey()获取Entry键
getValue()获取Entry对象的值

泛型

泛型,用来灵活的将数据类型应用到不同的类、方法、接口当中,将数据类型作为参数传递。

异常

异常

指的就是程序在运行过程中,出现的非正常的情况,会导致程序非正常停止

Error:严重错误,无法通过处理的错误,只能写程序时尽量避免

Exception:表示异常,可以通过处理之后,使程序继续运行

常见的异常

一、编译时异常(Checked Exception)

  编译时异常是在编译阶段检测到的异常,它们通常表示程序可能无法正常执行的情况,需要在代码中进行处理。常见的编译时异常包括:

  1.IOException(输入输出异常)

  当发生输入或输出操作失败时,比如文件读写错误或网络连接问题,会抛出IOException。处理该异常可以使用try-catch语句捕获并处理异常,或者在方法声明中使用throws关键字声明抛出该异常。

  2.SQLException(SQL异常)

  SQLException是处理数据库操作时可能发生的异常,如连接数据库失败、执行SQL语句错误等。处理方法与IOException类似,可以使用try-catch语句捕获并处理异常,或在方法声明中声明抛出SQLException。

  3.ClassNotFoundException(类未找到异常)

  当试图加载某个类时,但找不到该类时,会抛出ClassNotFoundException。常见的情况是未正确配置类路径或引入依赖库。处理该异常可以通过检查类路径或引入正确的库来解决。

二、运行时异常(Unchecked Exception)

  运行时异常是在程序运行过程中检测到的异常,它们通常表示程序错误或逻辑错误。与编译时异常不同,运行时异常不需要在代码中强制进行处理,但我们仍然应该尽力避免它们的发生。以下是几个常见的运行时异常:

  1.NullPointerException(空指针异常)

  当尝试访问空引用或未初始化的对象时,会抛出NullPointerException。为了避免该异常,我们应该在使用对象之前进行非空判断。

  2.ArrayIndexOutOfBoundsException(数组越界异常)

  当尝试访问数组的索引超出有效范围时,会抛出ArrayIndexOutOfBoundsException。为了避免该异常,我们应该确保使用合法的数组索引。

  3.ArithmeticException(算术异常)

  当进行除零操作或其他不合法的数学运算时,会抛出ArithmeticException。为了避免该异常,我们应该在进行除法运算之前进行适当的检查。

三、自定义异常(Custom Exception)

  除了Java提供的标准异常之外,我们还可以根据需求创建自定义异常。自定义异常可以继承自Exception或RuntimeException类,并根据具体情况添加自定义信息和逻辑。通过自定义异常,我们可以更好地捕获和处理特定的错误情况。

异常的捕获try…catch

  1. 将有可能发生异常的代码放在try语句中,将有可能发生异常的种类放在catch的参数中,catch语句块中处理异常、
1
2
3
4
5
6
7
8
9
try{

//要监听的代码

}catch(异常类型 异常名变量){

//针对异常进行处理的代码

}

  1. 当有多个异常种类时可以用多个catch语句进行捕获,一但捕获到某个异常try语句中,程序停止不再执行,会往下运行其他程序

  2. 如果try语句中还有其他异常,而catch语句并没有捕获到,可以在最后加一个catch语句,参数为所有异常的父类Exception,它能够捕获到所有的异常,但是一旦前面的某一个catch捕获到了异常,后面的所有catch语句将不在进行捕获。

finally语句块

当程序发生异常时在catch语句中捕获到,并进行处理时,可能会让程序发生跳转或者返回等等。这时发生try…catch后面的语句就不再执行,为了解决这个问题,finally语句块中的程序是无论是否发生异常都会去执行的代码。

异常的抛出throw

1.当程序发生异常时,不做处理,可以抛出给调用者,让调用者处理。throw是写在方法内部,该方法的声明处要用throws关键字抛出异常种类。

2.当方法内部用了多了throw,抛出多个异常时,在方法的声明处,用throws关键字抛出多个异常种类,用逗号隔开。

线程

并发:在同一时刻,有多个指令在单个CPU上交替执行

并行:在同一时刻,有多个指令在多个CPU上同时执行

进程:一个内存中运行的应用程序,每个进程都有独立的内存空间,一个应用处程序可以有多个进程

线程:是最小的执行单元,一个进程中可以有多个线程

多线程:程序可以同时运行多个任务

创建线程(继承Thread)

  1. 定义一个Thread的子类,并重写run()方法,run()方法就代表了线程需要完成的任务

  2. 创建Thread子类的对象

  3. 调用线程的start()方法来启动线程

    image-20230806152749452

    结果:两线程随机交替执行100次“hello world”

创建线程(通过Runnable接口):

  1. 定义Runnable的实现类,重写该接口的run()方法

  2. 创建该实现类的类对象并以此类对象作为Thread的参数来创建Thread对象,该对象才是真正的线程对象。

  3. 调用start()方法来启动线程

    image-20230806152950189

    结果:两线程随机交替执行100次“hello world”

Thread类主要方法

方法名称 说明
String getName() 返回此线程的名称
void setName(String name) 设置线程的名字(构造方法也可以设置名字)
static Thread currentThread() 获取当前线程的对象
static void sleep(long time) 让线程休眠指定的时间,单位为毫秒
setPriority(int new Priority) 设置线程的优先级
final int getPriority() 获取现成的优先级
final void setDaemon(Boolean on) 设置为守护线程
public static void yieId() 出让线程/礼让线程
public static void join() 插入线程/插队线程

线程的优先级

线程调度方式:

抢占式调度:主打一个随机性,谁抢到算谁的。线程的优先级有十个档次,0为最低。但是要注意,这不代表优先级高的就一定先执行完,他只是概率会很大。

守护线程

image-20230806164925334

当把一个进程设置为守护进程时,当主进程执行完而守护进程没有执行完,就会逐渐结束。

应用场景:QQ聊天并传送文件,聊天和文件传输各使用一个进程,当聊天页面被关闭时,文件传输进程也会随之关闭

线程生命周期

image-20230806171821089

线程安全

什么是线程安全

当一个共享资源被多个线程共享时各个线程不相通,所以就会形成线程多次执行同一个任务

为了解决这个问题java提供了同步锁和Lock锁

同步锁格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MyThread extends Thread{
static int ticket=0;
static Object object=new Object();

public void run(){
while (true) {
synchronized (object) {
if (ticket < 100) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
ticket++;
System.out.println(getName() + "正在卖第" + ticket + "张票!!!");
} else {
break;
}
}
}
}
}

Lock锁格式:

image-20230806190429892

public void lock();加同步锁

public void unlock();解锁

线程状态

等待唤醒机制

  1. wait:线程不再活动,进入wait set中,不会浪费cpu,这时的状态就是waiting,必须等着另一个线程执行唤醒notify动作,把在waiting中的线程唤醒,这时waiting 中的线程从waiting set中释放出来。

  2. notify:从waiting set中选取一个线程释放,

  3. notifyAll:把waiting set中所有的线程唤醒。

注意事项:从waiting set中释放的线程并不代表可以立即恢复执行,只是进入可执行状态;

注意事项:

1.wait和notify方法必须要用同一个锁对象,锁对象只能唤醒同一个锁对象中等待的线程。

2.锁对象可以是任意对象。

3.wait和notify方法必须要放在同步代码块或者同步方法中。

函数式编程

Lambda表达式

什么是lambda表达式

是一种简化匿名内部类的方法,并不是所有的匿名内部类都能简化,前提是必须是一个接口并且接口中只有一个抽象方法

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
public class xianc implements Runnable {

@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"正在运行");
}
}


public class Test {
public static void main(String [] args) {
xianc xc=new xianc();
Thread th=new Thread(xc);
th.start();

//匿名内部类
Thread th=new Thread(new Runnable(){
public void run(){
System.out.println(Thread.currentThread().getName()+"正在运行");
}
});
th.start();

//Lambda表达式
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"正在运行");
}).start();
}
}

File文件类

构造方法

public File(String pathname);通过给定的路径名字符串创建File实例。

public File(String parent,String child);第一个参数是父路径,第二个参数是文件名。

public File(File parent,String chilid);第一个参数是通过父路径创建的File实例。

常用方法

public String getAbsolutePath():返回文件的绝对路径。

public String getPath();返回路径名的字符串,即定义File对象实例时,传进去的参数。

public String getName();获取文件的名称

public long length();获取文件的大小。

判断功能方法

public boolean exists();用于判断指定路径中文件是否存在

public boolean isDirectory();用于判断路径是否是一个目录

public boolean isFile();用于判断路径是否是一个文件

创建和删除功能

public boolean createFile();当文件或目录不存在的时候返回true并创建,如果存在就返回false

public boolean delete();当文件存在时返回true否则返回false

public boolean mkdir();创建一个目录

public boolean mkdirs();创建多级目录

遍历目录

public String[] list();返回一个String数组,表示该File目录中的所有子文件和目录。

只能输出一级目录下的文件和目录。

1
2
3
4
5
6
7
8
9
10
public static void main(String [] args) {  
File dir=new File("F:"); /*创建文件对象*/

String [] names= dir.list();

for(String i:names){
System.out.println(i);
}
}
}

5201314.pptx

实训练习

WordPress mysqle

外星人就在月球背面.txt

课件

软件安装包

public File[] listFile();返回是一个File数组,表示该File目录中的所有子文件和目录。只能输出一级目录下的文件和目录。

1
2
3
4
5
6
7
8
9
10
public static void main(String [] args) {

File dir=new File("F:"); /*创建文件对象*/
File [] names= dir.listFiles();

for(File i:names){
System.out.println(i);
}
}

都是一级文件
/* F:$RECYCLE.BIN
F:5201314.pptx
F:实训练习
F:WordPress mysqle
F:外星人就在月球背面.txt
F:课件*/

文件过滤器

导入java.io.FileFilter;是一个接口,里面有一个抽象方法:

boolean accept(File name);

例子:保留所有.java类型的文件

方法一:先建立一个FileFilter的实现类,重写accept方法,然后在测试类里,创建该实现类的类对象,遍历目录中的所有文件,每层循环都调用一次该对象中的accept方法,返回true则输出该文件,否则不输出。

FileFilter的实现类:

1
2
3
4
5
6
public class bianlimulu implements java.io.FileFilter{

@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".java");
}

测试类:

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String [] args) {

File file=new File("F://");
File [] dir=file.listFiles(); /*创建数组接收文件*/
FileFilter ff=new bianlimulu(); /*利用多态创建对象*/
for(File a:dir){ /*遍历数组元素*/
if(ff.accept(a)){ /*如果末尾是.java*/
System.out.println(a); /*输出*/
}
}
/*F:\\abc3.java*/
}

方法二:对方法一种,不再单独写一个类,而是用内部类来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class bianlimulu{

public static void main(String [] args) {
File file=new File("F:");
File [] list=file.listFiles();
FileFilter ff=new FileFilter(){
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".java");
}
};
for(File f:list){
if (ff.accept(f)) {
System.*out*.println(f);
}
}
}
}

字节流和字符流

IO的分类

输入流:把数据从其他设备上读取到内存中

输出流:把数据从内存中写出到其他设备

字节流和字符流

字节流:以字节为单位,读写数据

字符流:以字符为单位,读写数据

字节流

  1. OutputStream类是一个抽象类,表示所有字节的输出流的父类。

导入java.io.FileOutputStream;必须写在try语句中,或者抛出异常IOException。

File dir=new File(“E:\\aaa.txt”);

FileOutputStream fos=new FileOutputStream(dir,true);

一次存放多个字节

  1. InputStream类是一个抽象类,表示所有字节的输出流的父类。

导入java.io.FileInputStream;必须写在try语句中,或者抛出异常IOException。

File dir=new File(“E:\\aaa.txt”);

FileInputStream fos=new FileInputStream(dir);

读一个字符

字符流

  1. 字符输出流

当用字节流读写文件时,可能会遇到一个问题,就是遇到中文字符时,会显示乱码,这个时候可以用字符流来读取文件

字符输出流:Reader类是一个抽象类,用来读取文件内容,常用得一个子类就是FileReader,导入java.io.FileReader;

字符输入流:Writer类是一个抽象类,用来读取文件内容,常用得一个子类就是FileReader,导入java.io.FileWriter;

  1. 构造方法

public FileWriter(File file);以File类对象为参数创建输出流

public FileWriter(String filename,boolean append);以文件名为参数,创建输出流,每次都是先把文件清空,在往里写内容。第二个参数代表是否追加,即每次写的时候是在文件后面追加内容,还是先清空,再重写,如果是true,则是追加,false是清空重写,默认是false.

  1. 字符输入流

导入java.io.FileReader;用来读取文件内容。

1,构造方法

(1)public FileReader(File file);参数为File类对象,创建一个字符输入流。

(2)public FileReader(String filename);参数为文件名,创建一个字符输入流。

2.读取字符数据

(1)read();一次读取一个字符

(2)read(char[] c);一次读取一个字符数组

关闭和刷新机制

我们在利用输出流写东西时,如果不调用close()方法,所写的内容是无法写出到文件上的,但是调用了close()方法,那么就无法再继续写内容,这个时候可以用刷新机制flush(),调用flush()方法,可以将之前写的内容都呈现在文件中。

文件输出:我爱你

缓冲流

缓冲流也就高效流。基本流中,每次读一次数据,写一次数据,频繁的IO操作,会降低程序运行的效率,缓冲流就是在创建流对象的时候,会创建一个缓冲区,通过缓冲区,将数据暂存在缓冲区,从而提高读写的效率。

1.字节缓冲流:

(1)字节缓冲输入流:BufferedInputStream(new FileInputSream())

(2)字节缓冲输出流:BufferedOutputStream(new OutputFormat

​ putStream())

2.字符缓冲流

(1)字符缓冲输入流:BufferedReader(new FileReader())

(2)字符缓冲输出流:BufferedWriter(new FileWriter())

效率测试字节缓冲流

(1)基本字节流

运行结果:224ms

(2)缓冲流

运行结果:3ms

(1)基本字符流

运行结果:45ms

(2)字符缓冲流

运行结果:17ms

转换流

程序中,读写的文件默认是utf-8,但是往往有些时候文件并不是utf-8而是GBK或者其他编码,这个时候程序在读写时可能会出错,这个时候可以用转换流来制定读取的文件编码

InputStreamReader类:它读取字节,并按照指定编码读取。

(1)构造方法:

public InputStramReader(InputStream in,String charsetName);创建一个指定字符集的字符流。

(2)指定编码读取

2.OutputStreamWriter:写出字节,按照指定编码

(1)构造方法

public OutputStreamWriter(OutputStream in);创建一个默认字符集的字符流

public OutputStramWriter(OutputStream in,String charsetName);创建一个指定字符集的字符流。

指定编码写出

序列化和反序列化

一个类对象要想序列化,这个类定义时必须实现一个接口Serializable,导入java.io.Serializable;

一、ObjectOutputStream类:序列化

构造方法:public ObjectOutputStream(outputStream out);

导入java.io.ObjectOutputStream;

1.定义一个序列化的类

2.在测试类里写出对象方法:writeObject()

  1. ObjectInputStream类:反序列化

构造方法:public ObjectInputStream(inputStream in);

导入java.io.ObjectInputStream;

读取对象序列化文件调用readObject()方法,必须抛出异常ClassNotFoundException;

属性集

导入java.util.Properties;使用键值对结果来存储数据,每一个键跟值都是字符串。

构造方法:

public Properties();

基本的存储方式

public object setProperty(String key,String value);保存一对的属性

public String getProperty(String key);通过键获取对应的属性值

public Set<String> stringPropertyNames();获取所有键的名称

与流有关的方法

1.public void load(InputStream in);从字节输入流中读取键值对。

  1. 前提是1.txt的文本存储内容为:

2.public void store(OutputStream out,String comment );将属性集内容写出到文本文件中。

网络通讯协议

通过计算机网络可以使用多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时要遵守一定的规则,被称为网络通讯协议,它对数据的传输格式、传输速率、传输步骤等做了统一的规定,通信双方必须同时遵守才能完成数据的传输和交换。

TCP/IP协议:传输控制协议。是面向连接的通信协议,即在传输之前,发送端和接收端建立连接,然后才传输数据,它提供了两台计算机之间可靠无差错的数据传输。三次握手:在发送端发送数据的准备阶段,客户端与服务器之间有三次交互,以保证连接的可靠。

第一次握手:客户端向服务器发送连接请求,等待服务器确认。

第二次握手:服务器端向客户端回送一个响应,通知客户端收到了连接请求。

第三次握手:客户端再次向服务器端发送确认信息,确认连接。

完成三次握手,客户端和服务器端就可以开始进行数据传输了,由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛。

UDP协议:用户数据报协议。无连接协议,数据发送端和接收端不建立连接,即当一台计算机向另一台计算机发送数据时,发送端不用确认接收端是否存在,就直接发送数据,同样,如果接收端接收到数据了,它也不会向发送端反馈是否收到数据。由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP。

特点:数据被限制在64kb以内,超出这个范围就不能发送了。

网络编程的三要素

  1. 协议:TCP/IP或UDP等等。

  2. IP地址:用来给一个网络中的计算机设备的唯一编号。IP地址分类主要分为IPV4和IPV6

  3. 端口号:每台计算机都有很多进程,如果说IP地址可以唯一的标识网络中的电脑,那么端口号就可以唯一的标识电脑中的进程(应用程序)。

端口号一般用两个字节来表示,取值范围0~65535.

利用协议+IP地址+端口号三元组合,就可以唯一的标识网络中的进程了。

TCP通信程序

两端(客户端和服务器端)通信时的步骤:

  1. 服务器端程序,需要先启动,等待客户端的连接。

  2. 客户端主动去连接服务器端,连接成功后才能通信,服务器端不可以主动连接客户端。

在Java中,提供了两个类用于实现TCP通信程序:

  1. 客户端:导入java.net.Scoket;创建Socket类对象,向服务端发出连接请求,服务端相应请求,两者连接开始通信。

  2. 服务器端:导入java.net.ServerSocket;创建ServerSocket对象,相当于开启一个服务,等待客户端的连接。

客户端Socket类

1.构造方法:public Socket(String host,int port);参数host代表的是要连接的服务器端的IP地址,port代表的指定的端口号。127.0.0.1代表的是本机地址。

2.成员方法:

(1)public InputStream getInputStream();返回输入流

(2)public OutputStream getOutputStream();返回输出流

(3)public void close();关闭套接字

(4)public void shutdownOutput();禁用此套接字的输出流。

服务器端ServerSocket类

1.构造方法:public ServerSocket(int port);port代表的指定的端口号。

2.成员方法:

(1)public Socket accept();侦听并接收连接,返回一个新的Socket对象,用于和客户端实现通信。

网络程序案例

服务器端

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
public class fuwuqiduan {

public static void main(String\[\] args) throws IOException {
//创建指定端口号
ServerSocket ss=new ServerSocket(6666);
/*侦听并接收连接*/
Socket server=ss.accept();
/*返回输入流*/
InputStream is=server.getInputStream();
byte [] b=new byte [100];
/*输入流读取返回到数组b*/
is.read(b);
for(byte i:b){
System.out.print((char)i);
}
/*输出流*/
OutputStream out=server.getOutputStream();
out.write("i am fine thanks".getBytes(StandardCharsets.*UTF\_8*));
out.close();
ss.close();
is.close();
}

/*alice,how are you*/
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class kehuduan {

public static void main(String [] args) throws IOException {
/*创建客户端对象*/
Socket client=new Socket("127.0.0.1",6666);
/*创建输出流*/
OutputStream os=client.getOutputStream();
os.write("alice,how are you".getBytes(StandardCharsets.UTF_8));
/*创建输入流*/
InputStream in=client.getInputStream();
byte [] b=new byte [20];
in.read(b);
for(byte i:b){
System.*out*.print((char)i);
}
os.close();
client.close();
}
}

XML文件操作

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class dom {

public static void main(String [] args) throws IOException, DocumentException {
/*创建XML对象*/
SAXReader reader=new SAXReader();

/*读取指定XML文件*/
Document docx=reader.read(new File("C:\\\\Users\\\\Administrator\\\\Desktop\\\\网课练习\\\\XML操作\\\\新建文本文档.XML"));

/*获取根节点*/
Element gen=docx.getRootElement();
System.*out*.println(gen.getName());

/*获取父节点下第一个子节点返回类型为Element*/
Element zi1=gen.element("author");

/*获取根节点下所有节点*/
List list1= gen.elements("author");
for(int i=0;i<list1.size();i++){
Element e1=(Element) (list1.get(i));
System.*out*.println(e1.getText());
}

/*向指定的节点内添加一个节点*/
Element son=zi1.addElement("age");
son.setText("female");

/*修改节点名*/
son.setName("性别");

/*获取当前节点的父节点 */
/*删除当前节点的子节点*/
Element p1=gen.getParent();
p1.remove(gen);

/*给节点添加属性*/
gen.addAttribute("id","12345");

/*节点修改属性*/
gen.setAttributeValue("class","4567");

/*节点删除属性*/
gen.remove(gen.attribute("class"));


/*创建输出文本字符集对象*/
OutputFormat f=OutputFormat.createPrettyPrint();

//指定用什么字符集保存
f.setEncoding("utf-8");
FileOutputStream fo=new FileOutputStream("C:\\\\Users\\\\Administrator\\\\Desktop\\\\网课练习\\\\XML操作\\\\新建文本文档.XML");

/*创建XMLWrite对象,第一个属性是字符编码,第二个属性是文件*/
XMLWriter w=new XMLWriter(fo,f);

//将document对象写入到硬盘
w.write(docx);
//关闭writer对象
fo.close();
w.close();
}
}

Excel文件操作

常见操作类:针对03版本,07版本只需把Hssp改为XSSf即可

  1. HSSFWorkBook:Excel的文档对象

  2. HSSFSheet:Excel文档中Sheet类

  3. HSSRRow:Excel的行类

  4. HSSFCell:Excel的列类

  5. HSSFFont:Ecel的字体类

  6. HSSFCellStyle:单元格样式表

创建一个Excel文件

1
2
3
4
5
6
HSSFWorkbook wb=new HSSFWorkbook();/*创建一个Excel操作对象*/

FileOutputStream fos=new FileOutputStream("D:\\\\a1.xls");
wb.write(fos);
fos.close();
wb.close();

常见方法

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public class Test {

public static void main(String [] args) throws IOException,ClassNotFoundException {

/*创建一个Excel操作对象*/
HSSFWorkbook wb=new HSSFWorkbook(); /*创建一个Excel操作对象*/
FileOutputStream fos=new FileOutputStream("D:\\\\a1.xls");
wb.write(fos);
fos.close();
wb.close();

/*读入一个Excel对象*/
FileInputStream fis=new FileInputStream("D:\\\\a1.xls");
wb=new HSSFWorkbook(fis);

/*创建一个sheet表*/
wb.createSheet("2022.9.14");
fos=new FileOutputStream("D:\\\\a1.xls");
wb.write(fos);
fos.close();

/*创建一个sheet操作对象,定位到第一张sheet*/
Sheet sheet= wb.getSheetAt(0);
System.out.println(sheet.getSheetName());/*获取sheet的名字并输出*/

/*添加行createSheet()*/
Row r=sheet.getRow(0);
if(r==null){
sheet.createRow(0);
System.out.println("创建了第一行");
}else{
sheet.getRow(0);
System.out.println("获取了第一行");
}

/*创建多个行*/
Row [] row=new Row[3];
for(int i=0;i<3;i++){
row [i]=sheet.createRow(i);
}

/*创建单元格*/
r=sheet.getRow(0);
for (int i = 0; i < 3; i++) {
r.createCell(i).setCellValue("数据"+i);
}

/*删除行内容,保留行*/
r=sheet.getRow(0);
sheet.removeRow(r);

/*直接删除行*/
sheet.shiftRows(1,1,-1);/*第一个参数是起始行,第二个参数是结尾行,-1代表下面的行上移*/

/*读取单元格名称*/
r=sheet.getRow(0);
Cell cell=r.getCell(0);
System.*out*.println(cell.getStringCellValue());/*输出单元格内容*/

fos=new FileOutputStream("D:\\\\a1.xls");
wb.write(fos);
wb.close();
}
}

java爬虫

Jsop类

主要是来完成对HTML的解析

parse(File in,String charctName);解析HTML文件

connect(String url);通过网络地址获取Document对象

Document类

获取整个html文档存放在Document类对象里,通过它可以获取Element和Elements对象

getElementById(String id);根据id属性获取唯一的Element对象。

getElementsByTag(String tagName);通过标签获取元素对象的集合。

getElementsByAttribute(String key);根据属性名称获取元素集合。

getElementsByAttributeValue(String key,String value);根据属性值获取元素的集合

解析HTML

1
2
3
String url="https://www.51miz.com/sound/?utm\_term=8027759&utm\_source=baidu2&bd\_vid=11472151438253179744";  
Document att= Jsoup.connect(url).get();
Elements sound=att.getElementsByTag("source");

Element类

1.getElementByid(String id);根据id属性获取唯一的Element对象。

2.getElementsByTag(String tagName);通过标签获取元素对象的集合。

3.getElementsByAttribute(String key);根据属性名称获取元素集合。

4.getElementsByAttributeValue(String key,String value);根据属性值获取元素的集合。

String attr(String key);根据属性名称获取属性的值。

String text();获取文本内容。

String html();获取标签体的所有内容,包含标签。

爬取图片

爬取视频

爬取音频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Test {

public static void main(String [] args) throws IOException {
String url="https://www.51miz.com/sound/?utm\_term=8027759&utm\_source=baidu2&bd\_vid=11472151438253179744";
Document att= Jsoup.connect(url).get();
Elements sound=att.getElementsByTag("source");

for (int i = 0; i < sound.size(); i++) {
Element e=sound.get(i);
String s=e.attr("src");
if(!s.startsWith("http")){
s="http:"+s;
}
URL videoUrl=new URL(s);
String path="E:\\\\迅雷下载\\\\下载"+i+".mp3";
File file=new File(path);
FileUtils.*copyURLToFile*(videoUrl,file);
}
}
}

Java反射

概念

反射是能够直接操作类中所有的内部属性和方法

为什么不直接new对象而是使用反射呢

静态编译:在编译时就已经给定了类型,绑定了对象

Student stu=new Student();

动态编译:在运行时才给定类型,绑定对象。

动态编译最大限度的发挥了java的灵活性,体现了多态的应用

动态编译的缺点:对性能影响大

反射机制的应用

java反射机制提供的功能

  1. 在运行时判断任意一个对象所属的类

  2. 在运行时构造任意一个类的对象

  3. 在运行时判断任意一个类所具有的成员变量和方法

  4. 在运行时获取泛型类型

  5. 在运行时调用任意一个对象的成员变量和方法

  6. 在运行时处理注释

  7. 生成状态代理(spring底层构造出的一个框架—应用工具)

反射相关的主要API

java.lang.Class:代表一个类(生成的对象叫做类对象)

  1. 第一种方法:通过class关键字获取类对象(多用于知道是什么类型或传参)
1
2
3
xcc xcc=new xcc();

Class<?> clazz=xcc.class;
  1. 第二种方法:通过class类的类方法forName来获取类对象(多用于指配文件,将类名定义在配置文件中,便于利用Java的反射机制生成类对象加载类)
1
Class claxx= Class.forName("包名");
  1. 第三种方法:通过class对象的getClass方法(多用于获取字节码的方式)
1
2
3
xcc xcc=new xcc();

Class clayy=xcc.getClass();
  1. reflect包

class类+java.lang.reflect=反射

java.lang包下的Class<T>表示一个正在运行的java应用程序中的类和接口是Reflection的起源

java.lang.reflect包下:

Field类:代表类对象的成员变量

Method类:代表类对象的方法

Constructor类:代表类的构造方法

Array类:提供了动态创建数组,以及访问数组的元素的静态方法

  1. Class类获取class的实例

通常情况下我们通过new Object来生成一个类的实例对象,但是有的时候没办法直接new我们就必须通过反射动态生成

实例化无参构造方法的对象:

1
2
3
Class.newInstance();

Class.getConstructor(new Class[]{}).newInstance(new Object[]{})

实例化有参构造方法

1
2
3
Constructor constr=classtype.getConstructor(new Class[]{String.class,int.class,boolean.class});

zhi cc=(zhi) constr.newInstance(new Object[]{"zhangsan",18,true});

调用构造方法

获取本身setName的所有方法

1
2
3
Method mee=classtype.getDeclaredMethod("setName",String.class);

System.out.println(mee.getName());

获取所有公有化的方法

1
Method[] mee=classtype.getMethods()

调用方法

1
met2.invoke(构造实例,"setName");

获取属性

1
2
3
4
5
Field fi2= classtype.getField("name");

field fi=clazz.getDeclaredField()

Field[] fi=clazz.getFields()

class类常用的方法

获取空参构造方法

1
2
3
Constructor con=clazz.getConstructor().newInstance()

Constructor con=clazz.getConstructor(new Class[]{})

获取有参构造

Constructor con=clazz.getCountructor(new Class[]{String.class,int.class})

获取所有公共方法

Method me=clazz.getMethod(“toString”,new Class[]{});

获取所有本身的方法

Method me=clazz.getMethods

类的加载与classLoader(类加载器)

  1. 类的加载过程

当程序主动使用某个类的时候。如果该类还未被加载到内存中则系统会通过三步进行该类的初始化

  1. 将类的class文件读入到内存中,并为之创建一个java.lang.Class对象,此过程由类加载器完成

  2. 将类的二进制数据合并到JRE当中

  3. jvm负责对类进行初始化

 

  1. 各个步骤具体操作

    1. 加载:将class文件字节码内容加载到内存当中,并将这些静态数据转换成方法区的运行时数据接口,然后生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口(引用地址)。所有需要访问和使用类数据的只能通过这个class对象。这个加载过程需要加载器的参与

    2. 链接:将java类的二进制代码合并到JVM的运行状态之中的过程

      1. ·验证:确保加载的类信息符合JVM规范,例如:以café开头,没有安全方面问题

      2. 准备:正式为变量(static)分配内存并设置变量默认初始值的阶段,这些内存都将在方法区进行分配

      3. 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程

    3. 初始化

      1. 执行类构造器<clinit>()方法的过程。类构造器<clinit>()方法是由编译器自动收集类中所有变量的赋值动作和静态代码块儿中的语句合并产生的

      2. 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化

      3. 虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步

JDBC技术

概念

jdbc就是java操作数据库的一套API

全称(Java DataBase Connectivity)

JDBC本质

sun公司定义的一套关系型数据库准则,即接口,各个厂商去实现这个接口,提供数据库的驱动jar包,使用JDBC实际上执行的就是jar中的实现类

JDBC API详解

DriverManager(驱动管理类)

  1. 注册驱动

Class.forName(“com.mysql.jdbc.Driver”);

可以省略

  1. 获取链接

Connection lian=DriverManager.getConnection(String url,String use,int password)

.getConnection属性值

  1. url链接路径

语法:jdbc:mysql://ip地址:端口号/数据库名称

示例:jdbc:mysql://127.0.0.1:3306/biglist

  1. Connection(连接数据库)

 

  1. 获取执行SQL的对象

con.createStatement()

  1. 事务管理

开启事务:setAutoCommit(boolean autoCommit);填true表示自动提交事务,false表示手动提交

提交事务:commit()

回滚事务:rollback()

PreparedStatement

PreparedStatement作用:

预编译SQL语句对象并切能执行:预防SQL注入问题

  1. Statement(执行SQL语句)

 

  1. ResultSet .executeQuery(sql)(结果集对象)

封装DQL查询语句的结果

ResultSet .executeQuery(sql)执行DQL语句,返回ResultSet对象

获取查询结果

boolean next();

  1. 将光标从前位置向前移动一行

  2. 判断当前行为有效行

返回值true和false

xxx getXxx(参数):获取数据

xxx:数据类型;如int getInt(参数);String getString(参数)

参数:

int:列的编号,从1开始

String:列的名称

  1. int executeUpdate(sql):执行DML、DDL语句

executeQuery 
用于产生单个结果集的语句,例如 SELECT 语句。 被使用最多的执行 SQL 语句的方法是 executeQuery。这个方法被用来执行 SELECT 语句,它几乎是使用最多的 SQL 语句。

executeUpdate
用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整数,指示受影响的行数(即更新计数)。对于 CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。

c3p0连接池

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
ComboPooledDataSource cpd=new ComboPooledDataSource();

Connection con= cpd.getConnection();

等同于

String url=”jdbc:mysql:///biglist”;

String name=”root”;

String pwd=”510609”;

Connection con=DriverManager.getConnection(url,name,pwd)

配置文件:必须放在src里面,并且只能叫c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<c3p0-config>
<!-- 默认配置,如果没有指定则使用这个配置 -->
<default-config>
<!-- 连接参数 -->
<property name="jdbcUrl">
jdbc:mysql://localhost:3306/biglist?serverTimezone=Asia/Shanghai
</property>
<property name="user">root</property>
<property name="password">510609</property>

<!-- 连接池参数 -->
<!--初始化申请的连接数量-->
<property name="initialPoolSize">5</property>
<!--最大的连接数量-->
<property name="maxPoolSize">10</property>
<!--超时时间-->
<property name="checkoutTimeout">3000</property>
</default-config>

命名的配置,可以通过方法调用实现
<named-config name="mySource">
<property name="user">root</property>
<property name="password">510609</property>
<property name="jdbcUrl">
jdbc:mysql://localhost:3306/a1?characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai
</property>
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<!-- 如果池中数据连接不够时一次增长多少个 -->
<property name="acquireIncrement">5</property>
<!-- 初始化数据库连接池时连接的数量 -->
<property name="initialPoolSize">5</property>
<!-- 数据库连接池中的最大的数据库连接数 -->
<property name="maxPoolSize">50</property>
<!-- 数据库连接池中的最小的数据库连接数 -->
<property name="minPoolSize">5</property>
</named-config>
</c3p0-config>

DBUtils

可以设置查询结果集的封装策略

QueryRunner qr=new QueryRunner(cpd);

QueryRunner类,用于执行数据库操作

query(con,sql语句,查询操作)用于执行查询

  • ArrayHandler:把结果集中的第一行数据转成对象数组。

  • ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到 List中。

  • BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。

  • BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。

  • ColumnListHandler:将结果集中某一列的数据存放到List 中。

  • KeyedHandler:将结果集中的每一行数据都封装到一个Map里,然后再根据指定的 key把每个Map再存放到一个 Map里。

  • MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。

  • MapListHandler:将结果集中的每一行数据都封装到一个Map 里,然后再存放到List。ScalarHandler:将结果集中某一条记录的其中某一列的数据存成object.

例如:

1
2
3
4
5
6
ComboPooledDataSource cpd=new ComboPooledDataSource();
Connection con= cpd.getConnection();
QueryRunner qr=new QueryRunner(cpd);
String sql="select * from dz";
Listshit list=qr.query(con,sql, new BeanListHandlershit(shit.class));
System.out.println(list);

shit表示javabean实现类:包括getset、空参构造、toString

update()用于执行增删改

ResultSetHandler接口,用于处理Result结果集

实现类:BeanHandler将结果集中的第一行数据封装在实现类对象中

Tomcat配置idea

如何在 IDEA 中创建并部署 JavaWeb 程序 (baidu.com)

服务器组件Servlet

快速入门

  1. 创建一个java ee项目

  2. 在src中创建一个类并且实现Servlet接口

  3. 实现接口中的抽象方法

  4. 配置Servlet

在web.xml文件中的web-app标签中写入:

<servlet>

1
2
3
4
5
6
7
8
<servlet>
<servlet-name>demo1</servlet-name>
<servlet-class>tom</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo1</servlet-name>
<url-pattern>/demo1</url-pattern>
</servlet-mapping>

执行原理:

  1. 当服务器接收到客户端浏览器的请求后,会解析url路径,获取访问的Servlet的路径

  2. 查找web.xml中是否有对应的<url-pattern>标签内容

  3. 如果有则会找到对应的<servlet-class>全类名

  4. Tomcat会将字节码文件加载进内存,创建类名的实例化对象

  5. 调用其方法

Servlet的生命周期

1.被创建(加载资源)

public void init() {
/*初始化方法,在Servlet创建时执行只会执行一次*/

}

设置什么时候被创建

指定Servlet的创建时机,在web.xml文件的Servlet下创建
1.第一次被访问时创建:<load-on-startup>的值为负数
2.在服务器启动时创建:<load-on-startup>的值为0或者正整数

2.提供服务

public void service() {

​ System.out.println(“hello service”);
​ /*提供服务的方法,每一次Servlet被访问时会执行,可执行多次*/
​ }

3.被销毁

public void destroy() {

​ /*销毁方法,在Servlet正常关闭时执行*/

}

在Servlet被销毁之前执行,一般用于释放资源

Other Articles
cover
js编程指南
  • 23/09/18
  • 18:15
  • 3.3k
  • 13
cover
HTML精讲
  • 23/09/18
  • 18:15
  • 3.1k
  • 13