
Java是sun公司开发的一门编程语言,目前被Oracle公司收购,编程语言就是用来编写软件的。
Java语言平台
cd… : 退回到上一级目录
cd : 退回到根目录
cd tools: 进入tools文件夹
d: : 回车 盘符切换
cd d:234 :进入d盘的234文件夹,再切换盘符(d:)才能进入d:234
dir : 列出当前目录下的文件以及文件夹
cls : 清除屏幕
ipconfig: 查看本机的相关网络配置
3.JDK和JREJDK与JRE的关系
a: JDK:它是Java开发运行环境,在程序员的电脑上当然要安装JDK;
b: JRE:Java Runtime Environment它是Java运行环境;
c: JDK包含了JRE。
实现跨平台需要依赖Java的虚拟机 JVM (Java Virtual Machine)
4.编写HelloWorld程序 4.1编写步骤(初学者)a: 创建一个普通文本文件,将其修改为.java文件。
b: 完成模板代码:
public class HelloWorld{
public static void main(String[] args) {
System.out.println(“Hello World!”);
}
}
c:保存
4.2编译、运行开启DOS窗口并切换到.java文件所在的目录 ,输入指令
编译:javac 空格 文件名.java //生成一个CLASS文件
javac helloworld.java
执行:java 空格 类名 //类名为CLASS 文件名称,不带后缀
java helloworld
基础语法 1.注释1:单行注释 //注释内容
2:多行注释 /注释内容/
3:文档注释 /*注释内容/
组成关键字的字母全部小写,有特殊颜色标记 ,注意String不是关键字
3.数据类型1B(字节)=8bit
常量就是不变的数据量, 在程序执行的过程中其值不可以发生改变
常量分类
a: 整数类型
十进制表示方式:正常数字 如 13、25等
二进制表示方式:以0b(0B)开头 如0b1011 、0B1001
十六进制表示方式:以0x(0X)开头 数字以0-9及A-F组成 如0x23A2、0xa、0x10
八进制表示方式:以0开头 如01、07、0721
b: 小数类型
如1.0、-3.15、3.168等
c: 布尔类型
true、false
d: 字符类型
如’a’,‘A’, ‘0’, ‘家’
字符必须使用’’ 包裹,并且其中只能且仅能包含一个字符。
e: 字符串类型
字符串String类型是一种引用类型,我们先了解作为常量类型的使用方式
如“我爱Java”,“0123”,“null”
字符串必须使用“”包裹,其中可以包含0~N个字符。
程序运行过程中,值可以改变
变量定义格式:数据类型 变量名= 变量值;
修改值格式:变量名=修改值;
注意:
a:名字不能重复
b:变量未赋值,不能使用(尚未初始化变量)
c:定义long类型变量时,为了防止整数过大,后面要+“L”
d:定义float类型变量时,为了防止类型不兼容,后面要+“F”
6.标识符 给类,接口,方法,变量等起名字时使用的字符序列
规则:由数字、字母、下划线(_)和美元符($)组成
注意:不能以数字开头,不能是关键字,区分大小写
标识符中常见的命名规则:
表示范围小的数据类型转换成范围大的数据类型
范围从小到大:byte–>short(char)–>int–>long–>float–>double
格式:范围大的数据类型 变量 = 范围小的数据类型值;
double d=100;//把100转换成double型
7.2强制类型转换表示范围大的数据类型转换成范围小的数据类型
格式:范围小的数据类型 变量 = (范围小的数据类型) 范围大的数据类型值;
int i = (int)6.718; //i的值为6
一般不建议,因为有数据丢失
运算符 1.算数运算符+、-、*、/、%(取余)
a:加法运算符在连接字符串时要注意,只有直接与字符串相加才会转成字符串。
b:除法“/”当两边为整数时,取整数部分,舍余数。当其中一边为浮点型时,按正常规则相除。
c:“%”为整除取余符号,小数取余没有意义。结果符号与被取余符号相同。
d:整数做被除数,0不能做除数,否则报错。
e:小数做被除数,整除0结果为Infinity,对0取模结果为NaN。
f:算数表达式中包含多个基本数据类型的值时,整个表达式类型提升到其中最高等级类型。
2.赋值运算符| 运算符 | 运算规则 | 范例 | 结果 |
|---|---|---|---|
| = | 赋值 | int a=2 | 2 |
| += | 加后赋值 | int a=2,a+=2 | 4 |
| -= | 减后赋值 | int a=2,a-=2 | 0 |
| *= | 乘后赋值 | int a=2,a*=2 | 4 |
| /= | 整除后赋值 | int a=2,a/=2 | 1 |
| %= | 取余后赋值 | int a=2,a%=2 | 0 |
++、–
单独使用时:i++和++i结果是一样的
参与操作时:int j=i++;先把i值赋给j,后i做++操作。
int j=i++;先i做++操作,后把i值赋给j。
4.关系运算符| == | != | > | >= | < | <= |
|---|---|---|---|---|---|
| 等于 | 不等于 | 大于 | 大于等于 | 小于 | 小于等于 |
| 运算符 | 名称 | 运算规则 |
|---|---|---|
| & | 逻辑与 | 都是true结果才为true |
| | | 逻辑或 | 有true结果就为true |
| ^ | 逻辑异或 | 结果不同为true,相同为false |
| ! | 逻辑非 | 结果相反 |
| && | 短路与 | 左边为真,右边执行;左边为假,右边不执行 |
| || | 短路或 | 左边为假,右边执行;左边为真,右边不执行 |
(条件表达式)?表达式1:表达式2;
判断条件表达式,结果为一个布尔值,
true,运算结果为表达式1,
false,运算结果为表达式2。
| 优先级 | 描述 | 运算符 |
|---|---|---|
| 1 | 括号 | ()、[] |
| 2 | 正负号 | +、- |
| 3 | 自增自减,非 | ++、–、! |
| 4 | 乘除,取余 | *、/、% |
| 5 | 加减 | +、- |
| 6 | 移位运算 | <<、>>、>>> |
| 7 | 大小关系 | >、>=、<、<= |
| 8 | 相等关系 | ==、!= |
| 9 | 按位与 | & |
| 10 | 按位异或 | ^ |
| 11 | 按位或 | | |
| 12 | 逻辑与 | && |
| 13 | 逻辑或 | || |
| 14 | 条件运算 | ?: |
| 15 | 赋值运算 | =、+=、-=、*=、/=、%= |
| 16 | 位赋值运算 | &=、=、<<=、>>=、>>>= |
格式:
for(初始化语句 ; 条件判断语句 ; 条件控制语句){
循环体;
}
2.while循环
格式:
初始化表达式;
while(条件判断语句){
循环体;
条件控制语句
}
3.do…while循环
格式:
初始化表达式;
do{
循环体;
条件控制语句
}while(条件判断语句);
4.区别
for循环和while循环是先判断后执行
do…while循环是先执行后判断
for循环结束后,初始化语句定义的自增变量归属for循环语法结构,不能再被访问
while循环结束后,初始化语句定义的自增变量不归属while循环语法结构,可以继续使用
无限循环存在的原因是并不知道循环多少次,而是根据某些条件,来控制循环
Ctrl+c可以结束死循环
6.嵌套循环格式:
for(初始化表达式; 循环条件; 操作表达式) {
………
for(初始化表达式; 循环条件; 操作表达式) {
执行语句
………
}
………
}
//打印正三角形
public class ForForDemo {
public static void main(String[] args){
for(int i = 0 ; i < 9 ; i++){//外循环,控制的是行数
for(int j = 0; j < i+1 ;j++){//内循环,控制的是每行的个数 System.out.print("* ");
}
System.out.println();
}
}
}
7.跳转控制语句
7.1break语句
跳出所在的循环体
提前结束本次循环,继续进行下次循环
格式1:
if(比较表达式) {
语句体;
}
执行流程:
先计算比较表达式的值,看其返回值是true还是false。
如果是true,就执行语句体;
如果是false,就不执行语句体。
格式2:
if(比较表达式) {
语句体1;
}else {
语句体2;
}
执行流程:
首先计算比较表达式的值,看其返回值是true还是false。
如果是true,就执行语句体1;
如果是false,就执行语句体2。
格式3:
if(比较表达式1) {
语句体1;
}else if(比较表达式2) {
语句体2;
}else if(比较表达式3) {
语句体3;
}
...
else {
语句体n+1;
}
执行流程:
首先计算比较表达式1看其返回值是true还是false,
如果是true,就执行语句体1,if语句结束。
如果是false,接着计算比较表达式2看其返回值是true还是false。
格式: 条件表达式?表达式1:表达式2;
执行流程:
判断条件表达式,结果为一个布尔值,
true,运算结果为表达式1,
false,运算结果为表达式2。
格式:
swtich(表达式){
case 常量1 :
语句体1;
break;
case 常量2 :
语句体2;
break;
case 常量3 :
语句体3;
break;
...
default:
语句体n+1;
break;//可省略
}
case穿透:在使用switch语句的过程中,如果多个case条件后面的执行语句是一样的,则该执行语句只需书写一次即可,这是一种简写的方式。
例如,要判断一周中的某一天是否为工作日,同样使用数字1~7来表示星期一到星期天,当输入的数字为1、2、3、4、5时就视为工作日,否则就视为休息日。
import java.util.Scanner;
public class SwitchDemo {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int week = sc.nextInt();
switch (week) {
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("工作日");
break;
case 6:
case 7:
System.out.println("休息日");
break;
default:
System.out.println("输入的数字不正确...");
break;
}
}
}
Random
用于产生随机数
1.导包:import java.util.Random;
2.创建对象:Random r=new Random();
3.获取随机数:int number=r.nextInt(10);//表示从[0,10)中获取随机数
int number=r.nextInt(10)+1;//表示从[1,11)中获取随机数
int number=r.nextDouble();// 产生[0,1)范围的随机数
键盘输入数据1.导包:import java.util.Scanner;
2.创建对象:Scanner sc=new Scanner(System.in);
3.接收数据:int x = sc.nextInt();
数组 1.格式数据类型[] 数组名;
int[] arr;
2.数组元素访问访问数组存储的元素,必须依赖于索引:数组名[索引]
3.动态初始化动态初始化 : 在定义数组时只指定数组的长度,由系统自动为元素赋初值的方式称作动态初始化。
格式:类型[] 数组名 = new 类型[长度];
int[] arr = new int[4];
new为数据申请内存空间
4.静态初始化静态初始化: 在初始化数组时还有一种方式叫做静态初始化,就是在定义数组的同时就为数组的每个元素赋值。
格式:类型[] 数组名 = new 类型[]{元素,元素,……};
int[] arr = new int[]{1,2,3,4};
简化格式:类型[] 数组名 = {元素,元素,元素,……};
int[] arr = { 1, 2, 3, 4 };
5.内存分配int[] arr = new int[4];
int[] arr:栈内存,使用完毕立即消失
new int[4]:堆内存,使用完毕,会在垃圾回收器空闲时间被回收
数组在初始化时,会为存储空间添加默认值。
6.数组操作两个常见异常数组的索引越界异常:ArrayIndexOutOfBoundsException
访问了数组中不存在的索引元素
空指针异常:NullPointerException
访问的数组已经不在指向堆内存的数据
int[] arr = {1,5,8};
System.out.println(arr[2]);
arr = null; // arr 不在保存数组的地址了
System.out.println(arr[2]);//报错
public class ArrayDemo1 {
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 }; // 定义数组
// 使用for循环遍历数组的元素
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]); // 通过索引访问元素
}
}
}
7.2获取最值
public class ArrayDemo2 {
public static void main(String[] args) {
int[] arr = { 4, 1, 6, 3, 9, 8 }; // 定义一个数组
int max = arr[0]; // 定义变量max用于记住最大数,首先假设第一个元素为最大值
// 下面通过一个for循环遍历数组中的元素
for (int x = 1; x < arr.length; x++) {
if (arr[x] > max) { // 比较 arr[x]的值是否大于max
max = arr[x]; // 条件成立,将arr[x]的值赋给max
}
}
System.out.println("max=" + max); // 打印最大值
}
}
方法
1.方法概述
方法(method):是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集
注意:
方法定义:方法必须先创建才可以使用
方法调用:方法创建后并不是直接运行的,需要手动使用后才执行
2.方法定义和调用 2.1定义格式:public static void 方法名(){
//方法体
}
方法名();
在main方法中调用
必须先定义后调用,否则程序报错
3.带参数方法的定义和调用 3.1带参数定义格式:public static void 方法名(参数){ ... }
参数为形参:数据类型+变量名 , 缺一不可,可多个参数,用逗号(,)隔开
3.2带参数调用格式:方法名(参数);
参数为实参:变量名/常量值,数量与类型必须与定义中一致
4.带返回值方法的定义和调用 4.1带返回值定义格式:public static 数据类型 方法名(参数){
return 数据;
}
返回数据与方法定义数据类型相匹配。
4.2带返回值调用格式:格式1:方法名(参数);
格式2:数据类型 变量名=方法名(参数);(变量接受)
方法的返回值通常会使用变量接收,否则该返回值将无意义
5.注意事项 5.1方法注意定义:
public static 返回值类型 方法名(参数){
方法体;
return 数据;
}
调用:数据类型 变量名=方法名(参数);
void类型的方法,直接调用即可
非void类型的方法,推荐用变量接收调用
方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载
基本类型:对于基本数据类型的参数,形式参数的改变,不影响实际参数的值
引用类型:对于引用类型的参数,形式参数的改变,影响实际参数的值
DebugDebug:查看程序的执行流程,调试程序(断点调试)
Debug使用注意:如果数据来自于键盘输入,一定要输入数据,不然就不能继续往下查看了
面向对象基础 1.类和对象类是对现实生活中一类具有共同属性和行为的事物的抽象。
1.1类的特点:属性和行为
创建对象:类名 对象名= new 类名();
使用对象:
| 区别 | 成员变量 | 局部变量 |
|---|---|---|
| 类中位置不同 | 类中方法外的变量 | 方法中的变量 |
| 内存中位置不同 | 在堆内存 | 在栈内存 |
| 生命周期不同 | 随着对象的存在而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的调用完毕而消失 |
| 初始化值不同 | 有默认的初始化值 | 没有默认初始化值,必须先定义赋值才能使用 |
针对private修饰的成员变量,如果需要被其他类使用,提供相应的操作
一个标准类的编写:
this修饰的变量用于指代成员变量
什么时候使用this呢?解决局部变量隐藏成员变量
this:代表所在类的对象引用
通过方法来控制成员变量的操作,提高了代码的安全性
把代码用方法进行封装,提高了代码的复用性
4.构造方法 4.1概述构造方法是一种特殊的方法
作用:创建对象
格式:
public class类名{
修饰符类名(参数){}
}
功能:主要是完成对象数据的初始化
4.2注意事项构造方法的创建
构造方法的重载
推荐的使用方式
成员变量
构造方法
成员方法
创建对象并为其成员变量赋值的两种方式
nextLine()读取结果为String类型,返回String类型。
nextLine()读取回车符,并只以回车符结束。
next()、nextInt()看到空格符和回车符都认为读取结束。
2.String 2.1String概述String类在java.long包下,所以使用时不需要导包
字符串不可变,但可共享
效果上相当于char[],但底层原理是byte[]。
2.2构造方法:| 方法名 | 说明 |
|---|---|
| public String() | 创建一个空白字符串对象,不含有任何内容 |
| public String(char[] chs) | 根据字符数组的内容,来创建字符串对象 |
| public String(byte[] bys) | 根据字节数组的内容,来创建字符串对象 |
| String s = “abc” ; | 直接赋值的方式创建字符串对象,内容就是abc |
使用==作比较
equels()方法用来比较内容是否相同
charAt()对应的是索引对应值
endsWith()是否以此后缀结尾
补充创建对象和调用方法:Ctrl+Alt+V
3.StringBuilderStringBuilder对象中内容可变
3.1构造方法:| 方法名 | 说明 |
|---|---|
| public StringBuilder() | 创建—个空白可变字符串对象,不含有任何内容 |
| public StringBuilder(String str) | 根据字符串的内容,来创建可变字符串对象 |
| 方法名 | 说明 |
|---|---|
| public StringBuilder append(任意类型) | 添加数据,并返回对象本身 |
| public StringBuilder reverse() | 返回相反的字符序列 |
链式编程:sb.append("hello").append("world").append("java").append("100");
集合基础 1.集合ArrayList:可调整数组大小的数组实现。
:是一种特殊的数据类型,泛型。
2.构造方法| 方法名 | 说明 |
|---|---|
| public ArrayList() | 创建一个空的集合对象 |
| public boolean add(E e) | 将指定的元素追加到此集合的末尾 |
| public void add(int index,E element) | 在此集合中的指定位苦插入指定的元素 |
| 方法名 | 说明 |
|---|---|
| public boolean remove(Object o) | 删除指定的元素,返回删除是否成功 |
| public E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
| public E set(int index,Eelement) | 修改指定索引处的元素,返回被修改的元素 |
| public E get(int index) | 返回指定索引处的元素 |
| public int size() | 返回集合中的元素的个数 |
就是文件夹,用来分类管理
格式:package 包名(多级包用.分开)
自动建包:javac -d. HelloWorld.java
2.导包格式:import 包名;
自动导包:Alt+Enter
3.修饰符| 同一个类中 | 同一个包中子类无关 | 不同包子类 | 不同包无关类 | |
|---|---|---|---|---|
| private | √ | |||
| 默认 | √ | √ | ||
| protected | √ | √ | √ | |
| public | √ | √ | √ | √ |
final(最终):
final修饰局部变量:
变量是基本类型:final修饰的是基本类型的数据值不能变
变量是引用类型:final修饰的是引用类型的地址值不能变,但地址里面的内容可以变
final Student s = new Student();
s.age=10; 可以变
s=new Student(); 报错,不能变
static(静态):变量、方法
被类的所有对象共享
可以通过类名/对象名调用,推荐类名
静态成员方法只能访问静态成员。
继承是面向对象三大特征之一。可以使子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法。
2.格式class 子类 extends 父类 {}
(派生类)(基类、超类)
子类可以有父类的内容
子类还可以有自己特有的内容
好处:
弊端:
子类局部方法 ----子类成员 ----父类成员
age this.age super. age
本类对象引用 父类对象引用
子类成员 ----父类成员
8.方法重写方法重写就是子类中出现了和父类中一模一样的方法声明。
当子类需要父类的功能,而功能主体子类由自己的特有内容时,可以重写父类中的方法,这样既沿袭了父类的功能,又定义了子类特有的内容。
@Override(注解):可以帮助检查重写方法的方法声明的正确性。
注意:
同一个对象,在不同时刻表现出来的不同时态。
2.多态的前提和体现:成员变量:编译看左边,执行看左边
成员方法:编译看左边,执行看右边
因为成员方法有重写。
向上转型:从子到父,父类引用指向子类对象。
Animal a = new Cat();
向下转型:从父到子,父类引用转为子类对象。
Cat c = (Cat)a;
抽象类 1.抽象类描述在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类
2.抽象类的特点接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用,Java中的接口更多的体现在对行为的抽象
2.接口的特点内部类:就是在一个类中定义一个类。在一个类A的内部定义一个类B,类B就被成为内部类
内部类的访问特点
按照内部类在类中定义的位置不同,可以分为如下两种形式
成员内部类,外界如何创建对戏想使用呢?
前提:存在一个类或者接口,可以是具体类也可以是抽象类
本质:是一个继承了该类或者实现了该接口的子类匿名对象
常用API 1.mathmath包含执行基本数字运算的方法
没有构造方法,想要使用类中成员,就看类的成员是否都是静态的,如果是,通过类名直接调用
math 类的常用方法:
| 方法名 | 说明 |
|---|---|
| public static int abs(int a) | 返回参数的绝对值 |
| public static double ceil(double a) | 返回大于或等于参数的最小double值,等于一个整数 |
| public static double floor(double a) | 返回小于或等于参数的最大double值,等于一个整数 |
| public static int round(float a) | 按照四舍五入返回最接近参数的int |
| public static int max(int a,int b) | 返回两个int值中的较大值 |
| public static int min(int a,int b) | 返回两个int值中的较小值 |
| public static double pow(double a,double b) | 返回a的b次幂的值 |
| public static double random( | 返回值为double的正值,[0.0,1.0) |
System包含几个有用的类字段和方法,它不能被实例化
System类的常用方法:
| 方法名 | 说明 |
|---|---|
| public static void exit(int status) | 终止当前运行的Java虚拟机,非零表示异常终止 |
| public static long currentTimeMillis() | 返回当前时间(以毫秒为单位) |
currentTimeMillis()方法结果 :在1970年1月1日UTC之间的当前时间和午夜之间的差异,以毫秒为单位。
3.ObjectObject是类层次结构的根。 每个类都有Object作为超类。 所有对象(包括数组)都实现了这个类的方法。
构造方法:public Object()
看方法的源码,选中方法,按下Ctrl+B
Object类的常用方法:
| 方法名 | 说明 |
|---|---|
| public String toString() | 返回对象的字符串表示形式。建议所有子类重写该方法,自动生成 |
| public boolean equals(Object obj) | 比较对象是否相等。默认比较地址,重写可以比较内容,自动生成 |
Arrays类包含用于操作数组的各种方法。
Arrays类的常用方法:
| 方法名 | 说明 |
|---|---|
| public static String toString(int[] a) | 返回指定数组的内容的字符串表示形式 |
| public static void sort(int[] a) | 按照数字顺序排列指定的数组 |
工具类的设计思想:
冒泡排序:一种排序的方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,依次对所有的数据进行操作,直至所有数据按要求完成排序。
如果有n个数据进行排序,总共需要比较n-1次。
每一次比较完毕,下一次的比较就会少一个数据参与。
将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据。
5.1常用的操作之一:用于基本数据类型与字符串之间的转换
| 基本数据类型 | 包装类 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
包装一个对象中的原始类型int的值。
| 方法名 | 说明 |
|---|---|
| public Integer(int value) | 根据int值创建Integer对象(过时) |
| public Integer(String s) | 根据String值创建Integer对象(过时) |
| public static Integer valueOf(int i) | 返回表示指定的int值的Integer实例 |
| public static Integer valueOf(String s) | 返回一个保存指定值的Integer对象String |
Integer类中的String值只能为数字组成的字符串。
5.3 int和String的相互转换 int转换为String: public static String valueOf(int i)
String转换为int: public static int parseInt(String s)
5.4自动装箱和拆箱 装箱:把基本数据类型转换为对应的包装类类型
Integer i = 100;//自动装箱
拆箱:把包装类类型装换为对应的基本数据类型
i += 200;//i自动拆箱,i=i+200赋值后自动装箱
只要是对象,在使用前就必须进行不为null的判断
Date代表了一个特定的时间,以毫秒的精度。
6.1 Date类的构造方法:| 方法名 | 说明 |
|---|---|
| public Date() | 分配一个Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒 |
| public Date(long date) | 分配一个Date对象,并将其初始化为表示从标准基仙时间起指定的毫秒数 |
| 方法名 | 说明 |
|---|---|
| publie long getTime() | 获取的是日期对象从1970年1月1日00:00 00到现在的毫秒值 |
| public void setTime(long time) | 设置时间,给的是毫秒值 |
SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。重点学习日期格式化和解析
在日期和时间模式字符串中,从’A’到’Z’以及从’a’到’z’引号的字母被解释为表示日期或时间字符串的组件的模式字母。
常用的模式字母及对应关系如下:
| 年 | 月 | 日 | 时 | 分 | 秒 |
|---|---|---|---|---|---|
| y | M | d | H | m | s |
| 方法名 | 说明 |
|---|---|
| public SimpleDateFormat() | 构造一个SimpleDateFormat, 使用默认模式和日期格式 |
| public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat使用给定的模式和默认的日期格式 |
格式化(从Date到String):public final String format(Date date)
解析(从String到Date):public Date parse(String source)
6.6 Calendar类Calendar为某一时刻和一组日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法。
Calendar提供了一个类方法getInstance用于获取Calendar对象,其日历字段已使用当前日期和时间初始化:
Calendar rightNow = Calendar.getInstance();//多态的形式
6.7 Calendar的常用方法| 方法名 | 说明 |
|---|---|
| public int get(int field) | 返回给定日历字段的值 |
| public abstract void add(int field, int amount) | 根据日历的规则,将指定的时间量添加或减去给定的日历字段 |
| public final void set(int year,int month,int date) | 设置当前日历的年月日 |
c.add(Calendar.YEAR,10);//10年
c.add(Calendar.DATE,-5);//5天前
月是0-11,要设置3月,得写2
异常就是程序出现了不正常的情况
异常体系:
Throwable(Java语言中所有错误和异常的超类)分为Error和Exception
Exception分为RuntimeException和非RuntimeException
如果程序出现问题,我们没有做任何处理,最终JVM会做默认的处理
如果程序出现异常问题,我们需要自己来处理,有两种方案:
格式:try { 可能出现异常的代码; } catch(异常类名 变量名) { 异常的处理代码; }
执行流程:程序从try里面的代码开始执行,出现异常,会自动生成一个异常类对 象,该异常对象将被提交给JAVA运行时系统,当JAVA运行时系接收到异 常对象时,会到catch中去找匹配的异常类,找到后进行异常的处理, 执行完毕之后,程序还可以继续往下执行。
5.Throwable的成员方法| 方法名 | 说明 |
|---|---|
| public String getMessage() | 返回此throwable的详细消息字符串 |
| public String toString() | 返回此可抛出的简短描述 |
| public void printStackTrace() | 把异常的错误信息输出在控制台 |
Java中的异常被分为两大类: 编译时异常和运行时异常,也被称为受检异常和非受检异常,所有的RuntimeException类及其子类被称为运行时异常,其他的异常都是编译时异常
虽然我们通过try…catch…可以对异常进行处理,但是并不是所有的情况我们都有权限进行异常的处理也就是说,有些时候可能出现的异常是我们处理不了的,这个时候该怎么办呢?针对这种情况,Java提供了throws 的处理方案
格式:
throws异常类名;
注意: 这个格式是跟在方法的括号后面的
格式:
public class 异常类名 extends Exception { 无参构造 带参构造 }
throws
用在方法声明后面,跟的是异常类名
表示抛出异常,由该方法的调用者来处理
表示出现异常的一种可能性,并不一定会发生这些异常
throw
用在方法体内,跟的是异常对象名
表示抛出异常,由方法体内的语句处理
执行throw一定抛出了某种异常
范例:
public void checkScore(int score) throws ScoreException{
if(score<0 || score>180) {
throw new ScoreException("你给的分数有误,分数应该在0-100之间");
}else {
System.out.println("分数正常");
}
集合进阶
1.Collection
1.1 集合类的特点
提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变
集合类体系结构
1.2 Collection集合概述| 方法名 | 说明 |
|---|---|
| boolean add(E e) | 添加元素 |
| boolean remove(Object o) | 从集合中移除指定的元素 |
| void clear() | 清空集合中的元素 |
| boolean contains(Object o) | 判断集合中是否存在指定的元素 |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 集合的长度,也就是集合中元素的个数 |
ALt+7打开一个窗口,能够看到类的所有信息.
1.5 Collection集合的遍历 lterator:迭代器,集合的专用遍历方式
lterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到 Iterator
迭代器是通过集合的iterator)方法得到的,所以我们说它是依赖于集合而存在的
lterator中的常用方法
List集合特点
| 方法名 | 说明 |
|---|---|
| void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
| E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
| E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
| E get(int index) | 返回指定索引处的元素 |
并发修改异常:ConcurrentModificationException
产生原因:迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致
解决方案:用for循环遍历,然后用集合对象做对应的操作即可
2.4 ListlteratorListlterator:列表迭代器
Listlterator中的常用方法
增强for:简化数组和Collection集合的遍历
增强for的格式:
for(元素数据类型 变量名:数组或者Collection集合){
//在此处使用变量即可,该变量就是元素
}
范例:
int[] arr = {1,2,3,4,5};
for(int i : arr){
System.out.println(i);
}
2.6 数据结构
数据结构是计算机存储、组织数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。
2.7 常见的数据结构之栈数据进入栈模型的过程称为:压/进栈
数据离开栈模型的过程称为:弹/出栈
栈是一种数据先进后出的模型
2.8 常见的数据结构之队列数据从后端进入队列模型的过程称为:入队列
数据从前端离开队列模型的过程称为:出队列
队列是一种数据先进先出的模型
2.9 常见的数据结构之数组查询数据通过索引定位,查询任意数据耗时相同,查询速度快
删除数据时,要将原始数据删除,同时后面每个数据前移,删除效率低
添加数据时,添加位置后的每个数据后移,再添加元素,添加效率极低
数组是一种查询快,增删慢的模型
2.10 常见的数据结构之链表链表是一种增删快的模型(对比数组)
链表是一种查询慢的模型(对比数组)
2.11 List集合子类特点List集合常用子类:ArrayList,linkedList
| 方法名 | 说明 |
|---|---|
| public void addFirst(E e) | 在该列表开头插入指定的元素 |
| public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
| public E getFirst() | 返回此列表中的第一个元素 |
| public E getLast() | 返回此列表中的最后一个元素 |
| public E removeFirst() | 从此列表中删除并返回第一个元素 |
| public E removeLast() | 从此列表中删除并返回最后一个元素 |
Set集合特点
Set集合练习
哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值
对象的哈希值特点
HashSet集合特点
HashSet集合练习
HashSet集合添加一个元素的过程:
HashSet集合存储元素:
哈希表,JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组,JDK8以后,在长度比较长的时候,底层实现了优化
3.6 linkedHashSet集合概述和特点linkedHashSet集合特点
3.7 TreeSet集合概述和特点TreeSet集合特点
元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
TreeSet():根据其元素的自然非序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序
没有带索引的方法,所以不能使用普通for循环遍历
由于是Set集合,所以不包含重复元素的集合
集合存储基本数据类型的方法:使用包装类把基本类型包装成引用类型,这样集合就可以存储了。
3.8自然排序Comparable的使用存储学生对象并遍历,创建TreeSet集合使用无参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
结论
用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(To)方法
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
存储学生对象并遍历,创建TreeSet集合使用带参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
结论
泛型:是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型,它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数
一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?
顾名思义,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型。这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口。
泛型定义格式:
泛型的好处:
泛型类的定义格式:修饰符 class 类名<类型> {}
范例: public class Generic
此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
泛型方法的定义格式: 修饰符 <类型> 返回值类型 方法名(类型变量名) {}
范例:public
泛型接口的定义格式: 修饰符interface接口名<类型>{ }
范例: public interface Generic
为了表示各种泛型List的父类,可以使用类型通配符
如果说我们不希望List>是任何泛型L ist的父类,只希望它代表某一类泛型list的父类,可以使用类型通配符的上限
除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限
可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的
格式: 修饰符返回值类型方法名(数据类型...变量名){}
范例: public static int sum(int... a){ }
可变参数注意事项
Arrays工具类中有一个静态方法:
List接口中有一个静态方法:
Set接口中有一个静态方法:
Map集合概述
创建Map集合的对象
| 方法名 | 说明 |
|---|---|
| V put(K key,V value) | 添加元素 |
| V remove(Object key) | 根据键删除键值对元素 |
| void clear() | 移除所有的键值对元素 |
| boolean containsKey(Object key) | 判断集合是否包含指定的键 |
| boolean containsValue(Object value) | 判断集合是否包含指定的值 |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 集合的长度,也就是集合中键值对的个数 |
| 方法名 | 说明 |
|---|---|
| V get(Object key) | 根据键获取值 |
| Set keySet() | 获取所有键的集合 |
| Collection values() | 获取所有值的集合 |
| Set | 获取所有键值对对象的集合 |
我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
方式一:遍历思路
转换为Map集合中的操作:
方式二:遍历思路
转换为Map集合中的操作:
获取所有键值对对象的集合
Set
遍历键值对对象的集合,得到每一个键值对对象
用增强for实现,得到每一个Map.Entry
根据键值对对象获取键和值
用getKey()得到键用getValue0得到值
Collections类的概述
Collections类的常用方法
File:它是文件和目录路径名的抽象表示
文件和目录是可以通过File封装成对象的
对于file而言,其封摸的并不是一个真正存在的文件,仅仅是一个路径名而已。它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的
| 方法名 | 说明 |
|---|---|
| File(String pathname) | 通过将给定的路径名字符串转换为抽象路径名来创建新的File实例 |
| File(String parent, String child) | 从父路径名字符串和子路径名字符串创建新的File实例 |
| File(File parent, String child) | 从父抽象路径名和子路径名字符串创建新的File实例 |
| 方法名 | 说明 |
|---|---|
| public boolean createNewFile() | 当具有该名称的文件不存在时, 创建一个由该抽象路径名命名的新空文件 |
| public boolean mkdir() | 创建由此抽象路径名命名的目录 |
| public boolean mkdirs() | 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录 |
| 方法名 | 说明 |
|---|---|
| public boolean isDirectory() | 测试此抽象路径名表示的File是否为目录 |
| public boolean isFile() | 测试此抽象路径名表示的File是否为文件 |
| public boolean exists() | 测试此抽象路径名表示的File是否存在 |
| public String getAbsolutePath() | 返回此抽象路径名的绝对路径名字符串 |
| public String getPath() | 将此抽象路径名转换为路径名字符串 |
| public String getName() | 返回由此抽象路径名表示的文件或目录的名称 |
| public StringI] list() | 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组 |
| public File[ listFiles() | 返回此抽象路径名表示的目录中的文件和目录的File对象数组 |
| 方法名 | 说明 |
|---|---|
| public boolean delete() | 删除由此抽象路径名 表示的文件或目录 |
绝对路径和相对路径的区别
删除目录时的注意事项
递归指的是方法定义中调用方法本身的现象。
递归解决问题的思路:
把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算
递归解决问题要找到两个内容:
IO流概述:
IO流分类:
按照数据的流向
输入流:读数据
输出流:写数据
按照数据类型来分
字节流
字节输入流;字节输出流
字符流
字符输入流;字符输出流
如果数据通过Window自带的记事本软件打开,我们还可以读懂里面的内容,就使用字符流,否则使用字节流。如果你不知道该使用哪种类型的流,就使用字节流
2.2字节流写数据字节流抽象基类
FileOutputStream:文件输出流用于将数据写入File
使用字节输出流写数据的步骤:
| 方法名 | 说明 |
|---|---|
| void write(int b) | 将指定的字节写入此文件输出流,一次写一 个字节数据 |
| void wite(byte[] b) | 将b.length字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据 |
| void write(byte[]b, int off, int len) | 将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流,一次写一个字节数组的部分数据 |
字节流写数据如何实现换行呢?
写完数据后,加换行符
windows:rn
linux:n
mac:r
字节流写数据如何实现追加写入呢?
finally:在异常处理时提供finally块来执行所有清除操作。比如说IO流中的释放资源
特点:被finally控制的语句一定会执行,除非JVM退出
`try {
可能出现异常的代码;
}catch(异常类名变量名){
异常的处理代码;
}finally{
执行所有清除操作;
}`
2.6字节流读数据(一次读一个字节数据)
需求:把文件fos.txt中的内容读取出来在控制台输出
FilelnputStream:从文件系统中的文件获取输入字节
字节缓冲流:
构造方法:
由于字节流操作中文不是特别的方便,所以Java就提供字符流
用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼接成中文,如何识别是中文的呢?
基础知识:
字符编码:就是一套自然语言的字符与二进制数之间的对应规则(A:65)
字符集:
ASCll字符集:
GBXXX字符集:
Unicode字符集:
小结:采用何种规则编码,就要采用对应规则解码,否则就会出现乱码
3.3字符串中的编码解码问题使用何种字符集编码,就要使用相同的字符集解码
3.4字符流中的编码解码问题字符流抽象基类
字符流中和编码解码问题相关的两个类:
| 方法名 | 说明 |
|---|---|
| void write(int c) | 写一个字符 |
| void write(char[] cbuf) | 写入一个字符数组 |
| void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
| void write(String str) | 写一个字符串 |
| void write(String str, int off, int len) | 写-个字符串的一部分 |
| 方法名 | 说明 |
|---|---|
| flush() | 刷新流,还可以继续写数据 |
| close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一-旦关闭,就不能再写数据 |
| 方法名 | 说明 |
|---|---|
| int read() | 一次读一 个字符数据 |
| int read(char[] cbuf) | 一次读一 个字符数组数据 |
字符缓冲流:
构造方法:
BufferedWriter:
BufferedReader:
方式一:直接抛出处理,关注点在执行流程上
方式二:try{…}catch{…}finally{…}
try { 可能出现异常的代码; }catch(异常类名 变量名){ 异常的处理代码; }finally{ 执行所有清除操作; (还需要做try{...}catch{...}异常操作) }
方式三:JDK7(自动释放资源)
try (定义流对象){ 可能出现异常的代码; }catch(异常类名 变量名){ 异常的处理代码; }
方式四:JDK9(自动释放资源)
定义输入流对象; 定义输出流对象;
try (输入流对象;输出流对象){ 可能出现异常的代码; }catch(异常类名 变量名){ 异常的处理代码; }
System类中有两个静态的成员变量:
自己实现键盘录入数据:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
写起来太麻烦,就提供了一个类实现键盘录入
Scanner sc = new Scanner(System.in);
System类中有两个静态的成员变量:
输出语句的本质:是一个标准的输出流
打印流分类:
打印流的特点:
字节打印流
字符打印流PrintWriter的构造方法:
| 方法名 | 说明 |
|---|---|
| PrintWriter(String fileName) | 使用指定的文件名创建一个 新的PrintWriter,而不需要自动执行局新 |
| PrintWriter(Writer out, boolean autoFlush) | 创建一个新的PrintWriter ●out:字符输出流 ●autoFlush:一个布尔值,如果为真,则println, printf, 或format方法将刷新输出缓冲区 |
对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
要实现序列化和反序列化就要使用对象序列化流和对象反序列化流:
对象序列化流:ObjectOutputStream
构造方法:
序列化对象的方法:
注意:
对象反序列化流:ObjectInputStream
构造方法:
反序列化对象的方法:
用对象序列化流序列化了一个对象后, 假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
如果出问题了,如何解决呢?
如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
Properties概述:
是一个Map体系的集合类(不加泛型)
Properties可以保存到流中或从流中加载
Properties作为集合的特有方法:
| 方法名 | 说明 |
|---|---|
| Object setProperty(String key, String value) | 设置集合的键和值,都是String类型,底层调用Hashtable方法put |
| String getProperty(String key) | 使用此属性列表中指定的键搜索属性 |
| Set< String> stringPropertyNames() | 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串 |
Properties和IO流结合的方法:
| 方法名 | 说明 |
|---|---|
| void load(InputStream inStream) | 从输入字节流读取属性列表(键和元素对) |
| void load(Reader reader) | 从输入字符流读取属性列表(键和元素对) |
| void store(OutputStream out, String comments) | 将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(InputStream)方法的格式写入输出字节流 |
| void store(Writer writer, String comments) | 将此属性列表(键和元索对)写入此Properties表中,以适合使用load(Reader)方法的格式写入输出字符流 |
进程:是正在运行的程序
线程:是进程中的单个顺序控制流,是一条执行路径
方式1:继承Thread类
定义一个类MyThread继承Thread类 在MyThread类中重写run()方法 创建MyThread类的对象 启动线程
为什么要重写run()方法?
run()方法和start()方法的区别?
Thread类中设置和获取线程名称的方法:
线程有两种调度模型
Java使用的是抢占式调度模型
假如计算机只有一个CPU,那么CPU在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的
Thread类中设置和获取线程优先级的方法
线程默认优先级是5;线程优先级的范围是:1-10,越大越优先
线程优先级高仅仅表示线程获取的CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到你想要的效果
1.6线程控制| 方法名 | 说明 |
|---|---|
| static void sleep(long millis) | 使当前正在执行的线程停留 (暂停执行)指定的亳秒数 |
| void join() | 等待这个线程死亡 |
| void setDaemon(boolean on) | 将此线程标记为守护线程, 当运行的线程都是守护线程时,Java虚拟机将退出 |
方式二:实现Runnable接口
定义一个类MyRunnable实现Runnable接口 在MyRunnable类中重写run()方法 创建MyRunnable类的对象 创建Thread类的对象,把MyRunnable对象作为构造方法的参数 启动线程
锁多条语句操作共享数据,可以使用同步代码块实现
格式: synchronized(任意对象){ 多条语句操作共享数据的代码 }
synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁
同步的好处和弊端
同步方法:就是把synchronized关键字加到方法上
同步方法的锁对象是什么呢?
同步静态方法:就是把synchronized关键字加到静态方法上
同步静态方法的锁对象是什么呢?
StringBuffer
Vector
Hashtable
虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里加上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock
Lock实现提供比使用synchronized方法和语句可以获得更广泛的锁定操作
Lock中提供了获得锁和释放锁的方法
Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化
ReentrantLock的构造方法
生产者消费者模式是一个十分经典的多线程协作的模式,弄懂生产者消费者问题能够让我们对多线程编程的理解更加深刻所谓生产者消费者问题,实际上主要是包含了两类线程:
为了解耦生产者和消费者的关系,通常会采用共享的数据区域,就像是一个仓库
为了体现生产和消费过程中的等待和唤醒,Java就提供了几个方法供我们使用,这几个方法在Object类中Object类的等待和唤醒方法:
| 方法名 | 说明 |
|---|---|
| void wait() | 导致当前线程等待,直到另-个线程调用该对象的notify()方法或notifyAll()方法 |
| void notify() | 唤醒正在等待对象监视器的单个线程 |
| void notifyAll() | 唤醒正在等待对象监视器的所有线程 |
生产者消费者案例中包含的类:
奶箱类(Box):定义一个成员变量,表示第x瓶奶,提供存储牛奶和获取牛奶的操作
生产者类(Producer):实现Runnable接口,重写run0方法,调用存储牛奶的操作
消费者类(Customer):实现Runnable接口,重写run)方法,调用获取牛奶的操作
测试类(BoxDemo):里面有main方法,main方法中的代码步骤如下
计算机网络
网络编程
IP地址
端口
协议
IP地址:是网络中设备的唯一标识
IP地址分为两大类
常用命令:
特殊IP地址:
InetAddress:此类表示Internet协议(IP)地址
| 方法名 | 说明 |
|---|---|
| static InetAddress getByName(String host) | 确定 主机名称的IP地址。主机名称可以是机器名称,也可以是P地址 |
| String getHostName() | 获取此IP地址的主机名 |
| String getHostAddress() | 返回文本显示中的IP地址字符串 |
端口:设备上应用程序的唯一标识
端口号:用两个字节表示的整数,它的取值范围是0-65535。其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败
1.6协议协议:计算机网络中,连接和通信的规则被称为网络通信协议
UDP协议
用户数据报协议(User Datagram Protocol)
UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输
例如视频会议通常采用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议
TCP协议
传输控制协议(Transmission Control Protocol)
TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”
三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠
第一次握手,客户端向服务器端发出连接请求,等待服务器确认
第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求
第三次握手,客户端再次向服务器端发送确认信息,确认连接
完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛。例如上传文件、下载文件、浏览网页等
UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念
Java提供了DatagramSocket类作为基于UDP协议的Socket
发送数据的步骤
创建发送端的Socket对象(DatagramSocket)
DatagramSocket ds=new DatagramSocket();
创建数据,并把数据打包
byte[] bys="hello,udp,我来了".getBytes();
DatagramPacket dp=new DatagramPacket(bys,bys.length,InetAddress.getByName("半个有趣人"),10086);
调用DatagramSocket对象的方法发送数据
ds.send(dp);
关闭发送端
ds.close();
接受数据的步骤:
创建接收端的Socket对象(DatagramSocket)
DatagramSocket ds=new DatagramSocket(10086);
创建一个数据包,用于接收数据
byte[] bys=new byte[1024]; DatagramPacket dp=new DatagramPacket(bys,bys.length);
调用DatagramSocket对象的方法接收数据
ds.receive(dp);
解析数据包,并把数据在控制台显示
System.out.println("数据是:"+new String(dp.getData(),0,dp.getLength()));
关闭接收端
ds.close();
按照下面的要求实现程序
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信的两端形成网络虚拟链路,—旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信
Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信Java为客户端提供Socket类,为服务器端提供了ServerSocket类
3.2TCP发送数据发送数据的步骤
Socket s=new Socket("半个有趣人",10000);
OutputStream os = s.getOutputStream();
os.write("hello,tcp,我来了".getBytes());
s.close();
接收数据的步骤
创建服务器端的Socket对象(ServerSocket)
ServerSocket ss=new ServerSocket(10000); Socket s = ss.accept();
获取输入流,读数据,并把数据显示在控制台
InputStream is = s.getInputStream();
byte[] bys=new byte[1024];
int len=is.read(bys);
String data=new String(bys,0,len);
System.out.println("数据是:"+data);
释放资源
s.close(); ss.close();
练习1
客户端:发送数据,接收服务器反馈
先写数据,后读数据
服务器:接收数据,给出反馈
先读数据,后写数据
练习2
练习3
练习4
练习5
练习6
Lambda表达式的使用前提
练习1:
练习2:
练习3:
省略规则:
使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法
必须有上下文环境,才能推导出Lambda对应的接口
根据局部变量的赋值得知Lambda对应的接口:Runnable r = () -> System.out.printIn(“Lambda表达式”);
根据调用方法的参数得知Lambda对应的接口: new Thread(()-> System.out.printIn(“Lambda表达式”).start());
所需类型不同
使用限制不同
实现原理不同
接口的组成
常量
public static final
抽象方法
public abstract
默认方法(Java 8)
静态方法(Java 8)
私有方法(Java 9)
接口中默认方法的定义格式:
接口中默认方法的注意事项:
接口中静态方法的定义格式:
接口中静态方法的注意事项:
接口中私有方法的定义格式:
接口中私有方法的注意事项:
方法引用符
回顾一下我们在体验方法引用中的代码
Lambda表达式: usePrintable(s -> System.out.println(s));
分析:拿到参数s 之后通过Lambda表达式,传递给System.out.println方法去处理
方法引用: usePrintable(System.out::printIn);
分析:直接使用System.out中的 println方法来取代Lambda,代码更加的简洁
推导与省略
常见的引用方式:
引用类方法,其实就是引用类的静态方法
练习:
Lambda表达式被引用类方法替代的时候,它的形式参数全部传递给静态方法作为参数
1.4引用对象的实例方法引用对象的实例方法,其实就引用类中的成员方法
练习
Lambda表达式被引用类方法替代的时候,它的形式参数全部传递给该方法作为参数
1.5引用类的实例方法引用类的实例方法,其实就是引用类中的成员方法
练习
Lambda表达式被引用类方法替代的时候,第一个参数作为调用者,后面的参数全部传递给该方法作为参数
1.6引用构造器引用构造器,其实就是引用构造方法
练习
Lambda表达式被引用类方法替代的时候,它的形式参数全部传递给构造器作为参数
函数式接口 1.函数式接口 1.1函数式接口概述函数式接口:有且仅有一个抽象方法的接口
Java中的函数式编程体现就是Lambda表达式,所以函数式接口就是可以适用于Lambda使用的接口只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导
如何检测一个接口是不是函数式接口呢?
注意
需求
定义一个类(RunnableDemo),在类中提供两个方法
一个方法是: startThread(Runnable r)方法参数Runnable是一个函数式接口
一个方法是主方法,在主方法中调用startThread方法
如果方法的参数是一个函数式接口,我们可以使用Lambda表达式作为参数传递
startThread(0-> System.out.printin(Thread.currentThread0.getName()+ "线程启动了"));
需求
定义一个类(ComparatorDemo),在类中提供两个方法
一个方法是: Comparator getComparator()方法返回值Comparator是一个函数式接口
一个方法是主方法,在主方法中调用getComparator方法
如果方法的返回值是一个函数式接口,我们可以使用Lambda表达式作为结果返回
private static Comparator
Java 8在java.util.function包下预定义了大量的函数式接口供我们使用
Supplier:包含一个无参的方法
练习
Consumer:包含两个方法
练习
Predicate:常用的四个方法
练习
Function
R apply(T t):将此函数应用于给定的参数
default Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
Function
练习
Strings = "林青霞30*;
请按照我指定的要求进行操作:
1:将字符串截取得到数字年龄部分
2:将上一步的年龄字符串转换成为int类型的数据
3:将上一步的int数据加70, 得到一个int结果 ,在控制台输出
请通过Function接口来实现函数拼接
需求:按照下面的要求完成集合的创建和遍历
使用Stream流的方式完成过滤操作
Stream流的使用
Stream流的常见生成方式
Collection体系的集合可以使用默认方法stream()生成流
default Stream stream()
Listlist = new ArrayList (); Stream listStream = list. stream(); Set set = new HashSet (); Stream setStream = set. stream();
Map体系的集合间接的生成流
Mapmap = new HashMap (); Stream keyStream = map. keySet(). stream(); Stream valueStream = map. values(). stream(); Stream > entryStream = map . entrySet() . stream();
数组可以通过Stream接口的静态方法of(T… values)生成流
String[] strArray = {"he1lo", "world" , "java"};
Stream strArrayStream = Stream . of(strArray);
Stream strArrayStream2 = Stream. of("he11o","world", "java");
Stream intStream = Stream.of(10, 20, 30);
Stream filter(Predicate predicate):用于对流中的数据进行过滤
Predicate接口中的方法
boolean test(T t):对给定的参数进行判断,返回一个布尔值
Stream limit(long maxSize):返回此流中的元索组成的流,截取前指定参数个数的数据
Stream skip(long n):跳过指定参数个数的数据,返回由该流的剩余元索组成的流
static Stream concat(Stream a, Stream b):合并a和b两个流为一个流
Stream distinct():返回由该流的不同元素(根据Object.equals(Object) )组成的流
Stream sorted():返回由此流的元素组成的流,根据自然顺序排序
Stream sorted(Comparator comparator):返回由该流的元素组成的流,根据提供的Comparator进行排序
Stream map(Function mapper):返回由给定函数应用于此流的元素的结果组成的流
Function接口中的方法 R apply(T t)
IntStream mapTolnt(ToIntFunction mapper):返回一个IntStream其中包含将给定函数应用于此流的元素的结果
IntStream:表示原始int流
ToIntFunction接口中的方法 int applyAsInt(T value)
Stream流的常见终结操作方法
现在有两个ArrayLis集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作
对数据使用Stream流的方式操作完毕后,我想把流中的数据收集到集合中,该怎么办呢?
Stream流的收集方法
R collect(Collector collector)
但是这个收集方法的参数是一 个Collector接口
工具类Collectors提供了具体的收集方式
public static Collector toList(): 把元索收集到List集合中
public static Collector toSet(): 把元索收集到Set集合中
public static Collector toMap(Function keyMapper,Function valueMapper):把元索收集到Map集合中
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载,类的连接,类的初始化这三个步骤来对类进行初始化。如果不出现意外情况,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为类加载或者类初始化
类的加载
类的连接
类的初始化
类的初始化步骤
注意:在执行第2个步骤的时候,系统对直接父类的初始化步骤也遵循初始化步骤1-3
类的初始化时机:
类加载器的作用
JVM的类加载机制
ClassLoader:是负责加载类的对象
Java运行时具有以下内置类加载器
ClassLoader中的两个方法
Java反射机制:是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展
2.2获取Class类的对象我们要想通过反射去使用一个类,首先我们要获取到该类的字节码文件对象,也就是类型为Class类型的对象这里我们提供三种方式获取Class类型的对象
Class类中用于获取构造方法的方法
Constructor类中用于创建对象的方法
练习1:通过反射实现如下操作
Class> c = Class.forName("com.youquren.Student4");
Constructor> con = c.getConstructor(String.class, int.class, String.class);
Object o = con.newInstance("林青霞", 30, "西安");
System.out.println(o);
练习2:通过反射实现如下操作
Student s = new Student(“林青霞”);
system.out.println(s);
暴力反射
public void setAccessible(boolean flag):值为true,取消访问检查
Class> c = Class.forName("com.youquren.Student4");
Constructor> con =c.getDeclaredConstructor(String.class);
con.setAccessible(true);
Object o = con.newInstance("林青霞");
System.out.println(o);
2.5反射获取成员变量并使用
Class类中用于获取成员变量的方法
Field类中用于给成员变量赋值的方法
练习:通过反射实现如下操作
Constructor> con = c.getConstructor(); Object o = con.newInstance();
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(o,"林青霞");
System.out.println(o);
Field ageField = c.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(o,30);
System.out.println(o);
Field addressField = c.getDeclaredField("address");
addressField.setAccessible(true);
addressField.set(o,"西安");
System.out.println(o);
Class类中用于获取成员方法的方法
Method类中用于调用成员方法的方法
练习:通过反射实现如下操作
Student s = new Student();
s.method1();
Method m1 = c.getMethod("method1");
m1.invoke(o);
Method m2 = c.getMethod("method2", String.class);
m2.invoke(o,"林青霞");
Method m3 = c.getMethod("method3", String.class, int.class);
Object obj = m3.invoke(o, "林青霞", 30);
System.out.println(obj);
System.out.println(ss);
s.function();
Method m4 = c.getDeclaredMethod("function");
m4.setAccessible(true);
m4.invoke(o);
2.9反射练习
练习1:我有一个ArrayList集合,现在我想在这个集合中添加一个字符串数据,如何实现?
ArrayListarray=new ArrayList (); array.add(10); array.add(20); Class extends ArrayList> c = array.getClass(); Method m = c.getMethod("add", Object.class); m.invoke(array,"hello"); m.invoke(array,"world"); m.invoke(array,"java"); System.out.println(array);
练习2:通过配置文件运行类中的方法
//加载数据
Properties prop=new Properties();
FileReader fr = new FileReader("E:\IDEA\IdeaProjects\JavaSE_Code\idea_test\class.txt");
prop.load(fr);
fr.close();
String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");
//通过反射来使用
Class> c = Class.forName(className);
Constructor> con = c.getConstructor();
Object o = con.newInstance();
Method m = c.getMethod(methodName);
m.invoke(o);
模块化
1.模块化
1.1模块的基本使用
模块的基本使用步骤
注意:写模块名报错,需要按下Alt+Enter提示,然后选择模块依赖
1.2模块服务的使用模块服务的使用步骤