JavaSE笔记库

目录

Java简介

Java的版本

Java的版本类型

Java语言特点

Java平台的组成部分

第一个Java程序

输出语句

转义字符\

JAVA和JAVAC命令的作用

数据类型

变量

控制台输入

类型转换

运算符

算数运算符

关系运算符

逻辑运算符

条件运算符

流程控制

快捷键

随机数

数组

面向对象

封装

构造器(构造方法)

静态方法(类方法)

继承

重写

多态

final

抽象

接口

内部类

常用类

String字符串

包装类型

正则表达式

Object

Math

日期类

补充

泛型

集合

异常

File

IO流

多线程


Java简介

Java发布于1995年5月23日,Java前身是Oak,衍生自C++,Java之父是詹姆斯·亚瑟·高斯林,Java最早是sun公司的产品,2009年被Oracle公司收购,现属于Oracle公司的产品。

Java的版本

最初版本

1995年1.0版本;1.1版本

Java2平台

1.2 1.3 1.4 5.0

走出Java2

6

易主Oracle

2011年7,8

新的举措,每半年发布一个版本

9,10,11,12,13...

Java的版本类型

1.JavaSE,Java标准版本,可以开发Java控制台程序,桌面程序等,为JavaEE提供基础

2.JavaEE,Java企业级版本,现在以捐献给eclipse基金会,改名为雅加达EE(JakartaEE)。它是一套规范,由第三方对它具体实现,如tomcat、WebLogic等。在实际开发中,一般使用框架来代替它

3.JavaME,Java微版本,开发电冰箱,机顶盒,电烤箱,功能手机等设备中的嵌入式程序。

但智能手机程序不用Java ME开发。

Java语言特点

简单易学 废弃c中的指针操作

跨平台 不区分系统=》编译一次。到处执行

面向对象

健壮性

动态性

分布式

多线程

Java平台的组成部分

JVM:Java虚拟机额,使Java程序跨平台

JRE:Java运行环境,包含JVM,以及常用类库,运行Java程序的最小单位

JDK:Java开发工具包,包含JRE,以及编译工具,打包工具等,开发Java程序的最小单位

第一个Java程序

创建项目:File→New(Other)→Java Project →Project name →Finish →no

创建包:src右键→new→Package→Name→Finish

创建类:在包上右键→New→Class→Name→Finish

注释

// :单行注释

/**/:多行注释

/** */:文档注释

输出语句

  1. 不换行输出:System.out.print()

  2. 换行输出:System.out.println()

转义字符\

双引号:"

单引号:'

反斜线:\

制表符:\t(Tab键,适合不对齐的输出)

换行:\n

第一个Java程序

public 公共的 class类 static 静态的 void 没有返回值 String 字符串

System系统 out输出 println打印并换行

//定义包
package cn.etc.java.d0810;
//定义类,类名要和文件名必须一致
public class Hello {
	//主方法,是一个程序的入口
	public static void main(String[]args) {
		/*
		 * 	输出语句:
		 * 	1.不换行输出:System.out.print();
		 * 	2.换行输出:System.out.println();
		 * 
		 * 	转义字符:\
		 * 	1.双引号:\"
		 * 	2.单引号:\'
		 * 	3.反斜线:\\
		 * 	4.制表符:\t(Tab键,适合不齐的输出)
		 * 	5.换行:\n
		 */
		System.out.println("高斯林");
		System.out.println("1955");
		System.out.println(2021-1955);
		//Hello "World"
		System.out.println("Hello\nWorld");
//		System.out.println("Hello");
//		System.out.println("World");
	}
}

JAVA和JAVAC命令的作用

JAVAC:作用是JAVA编译器将.java文件编译生成.class字节码文件

JAVA:java命令作用是指JAVA解释器用于将.class字节码文件解释并执行

数据类型

1.基本数据类型

整数类型

byte 字节型 1个字节 8位 范围:-128~127

short 短整型 2个字节 16位 范围:-32768~32767

int(默认) 整型 4个字节 32位 范围:约正负21亿

long 长整型 8个字节 64位 范围:约正负92亿亿 后缀:L或l

浮点类型

float 单精度 4个字节 32位 后缀:F或f

double 双精度 8个字节 64位 后缀:D或d

字符类型

char 字符型 2个字节 16位 范围:0~65535(\u00000~\uffff)

布尔类型

boolean 布尔型 1或4个字节 8或32位 值:true false

2.引用数据类型

类类型(class)

字符串(String):多个字符组成了字符串,用引号表示,如“高斯林”,属于类类型

数组类型(array)

接口类型(interface)

枚举类型(enum)

注解类型(annotation)

变量

java中在使用数据之前,必须要先声明

变量:程序中可以改变的量

变量的三大要素(三大组成部分)

数据类型 变量名 变量值

1.声明变量:数据类型 变量名; 如:short age;

2.变量赋值:变量名 = 值;如:age = 18;

3.声明变量并赋值:数据类型 变量名 = 值; double score = 98.5;

4.声明多个同一类型的变量:数据类型 变量名1,变量名2...

变量名的建议规范

变量名遵循驼峰命名法,即首字母小写,其后每个单词首字母大写

不建议使用汉字,尽量使用英文单词或拼音,要见名知意

不建议使用单个字母命名,约定俗成除外

不建议以下划线开头,不建议使用$

命名法:

驼峰命名法:classId

帕斯卡命名法:ClassId

蛇底式命名法:class_id

尖叫蛇底式命名法:CLASS_ID

标识符强制规范

1.可由字母,数字,下划线,$组成

2.不能以数字开头

3.字母区分大小写

4.不能使用关键字,字面量,保留字命名

5.在同一作用域下同一种类型的名称不能重名

关键字:是Java定义好的具有特定含义的单词,如:public,int,class...

保留字:是Java的前身Oak和前代语言C、C++中的关键字,但是在Java中没有使用却保留下来的。goto,const

字面量:是Java定义好的一些值。如:true,false,null

命名习惯:

类名,接口名等:首字母大写,多个单词每个单词首字母均大写 Animal HelloWorld

方法名:小写,多个单词, 第二个单词之后首字母大写 main getName

变量名:小写,多个单词, 第二个单词之后首字母大写 name age stuName

包名:小写

常量名字:大写

public static void main(String[] args) {
//		double score;
//		score = 95.5;
		double score = 95.5;
		//字符串拼接:+
		System.out.println("成绩:"+score);
		System.out.println("score");
		//错误写法,num没赋值
//		int num;
//		System.out.println(num);
		
		int a = 10,b,c;
		System.out.println(a);
	}

 

public static void main(String[] args) {
		//整数型声明并赋值
		byte b = 127;
		short s = 32767;
		int i = 222222222;
		// 默认是int类型,long超出int范围需要加L/l
		long l = 111111111111111L;
		
		//浮点型声明赋值,默认是double 单精度必须加F/f
		float f = 3.14F;
		double d = 4.5;
		
		//字符型
		char c1 = 'a',c2 = '1',c3 = '你';
		
		//布尔类型 只能是true,false
		boolean b1 = false;
	}

控制台输入

Scanner 是用来输入的,首先定义一个Scanner

Scanner sc = new Scanner(System.in);

导入Scanner:

1.在package下面,写上import java.util.Scanner;

2.将鼠标放在Scanner上面,根据提示,选择...

3.将光标放在Scanner后面,按Alt+/(?)

4.使用快捷键:按Ctrl+Shift+o,会自动导入所有所需要的类

一般语法:sc.next类型(),类型要求首字母大写

输入double类型:sc.nextDouble();

输入int类型:sc.nextInt();

输入字符串String:sc.next();

没有char类型的输入

public static void main(String[]args) {
		Scanner sc = new Scanner(System.in);
		System.out.print("请输入你的成绩:");
		double score = sc.nextDouble();
		System.out.print("请输入你的年龄:");
		int age = sc.nextInt();
		System.out.println("请输入你的姓名:");
		String name = sc.next();
		System.out.println("成绩:"+score+",年龄:"+age+",姓名:"+name);
	}

类型转换

1.自动类型转换(隐式类型转换)

范围小的类型转到范围大的类型

2.强制类型转换(显示类型转换)

范围大的类型转到范围小的类型

(想要转到的类型)变量

强制类型转换可能会出现溢出(精度丢失)

3.在八大基本类型中,除了boolean之外的七种类型都可以互相转换

public class ConvertDemo {

	public static void main(String[] args) {
		
//		int boxOffice = 22;
//		long num = boxOffice;
//		System.out.println(num);
		
		long boxOffice = 2222222222L;
		int num = (int)boxOffice;
		System.out.println(num);
		
//		byte b = 1;
//		short s = b;
		
//		short s = 1;
//		byte b = (byte)s;
		
		byte a = 98;
		char c = (char)a;
		System.out.println(c);
		
		float f = (float)2.2;
		
		byte num2 = (byte)128;
		//a:97 A:65
		int i = 68;
		char cc = (char)i;
		System.out.println(cc);
	}

}

字符串转基本类型

一般语法:数据类型.parse数据类型(字符串),数据类型首字母大写

double score = Double.parseDouble("96.5");

1.字符串转int类型:Integer.parseInt(字符串);

int port = Integer.parseInt("3306");

2.对于字符串转布尔类型,如果字符串是true(不区分大小写),则结果是true,否则是false

3.没有转成char类型的方法

基本类型转字符串:

""+基本类型变量或者数值

public class StringConvertDemo {
	
	public static void main(String[] args) {
		
		String strScore = "95.5";
		System.out.println(strScore+1);
		double score = Double.parseDouble(strScore);
		System.out.println(score+1);
		
		String strPort = "3306";
		int port = Integer.parseInt(strPort);
		
		boolean ok = Boolean.parseBoolean("aaaa");
		System.out.println(ok);
		
		int a = 10;
		String str = ""+a;
	}

}

运算符

算数运算符,赋值运算符,关系运算符,逻辑运算符,条件运算符

算数运算符

+,-,*,/,%,++,--

1.两个整数相除的结果为整(即整),若想得到小数结果,需要将其中一个强制类型转换为浮点型 利用整除可以去掉最后一位:数/10 2.浮点类型的计算不一定精准(加减乘除)

3.取余数:

1)负数取余数,以第一个数的正负为准,若第一个数是正数,则结果为正,若第一个数是负数,则结果为负

2)判断奇偶:数%2,若结果是则是偶数,若结果为非0则是奇数

3)获取整数的最后一位:数%10

4)判断整数:数%1,若结果是0则是整数,若结果非0则是浮点数

4.两种类型进行计算的结果 1)都是整数类型,若为long类型参与,则结果为long类型,否则为int类型 2)若有浮点类型参与,如果有double类型参与,则结果为double类型,否则float类型

5.除了boolean之外的七种类型,都可以进行算数运算

6.++ 、-- ++:自加1 --:自减1 int i = 1; i++;//i变为2

i++和++i的区别 ​ i++:先用后加,先人后己 ​ ++i:先加后用,先己后人

//习题 ​ int j = 1; ​ //int sum3 = ++j + j++; ​ int y1 = ++j;//j=2 y1=2 ​ int y2 = j++;//j=3 y2=2 ​ int sum3 = y1+y2;//4 ​ System.out.println(j);//3 ​ System.out.println(sum3);//4

int aa = 1; ​ aa = aa++; ​ ... ​ System.out.println(aa);//值永远不变 ​ 在一行上,不建议写多个i++或者++i,违反了KISS原则。KISS:简单既是美

public class OperatorDemo01 {

	public static void main(String[] args) {
		System.out.println(1+2);
		System.out.println(5-1);
		System.out.println(2*6);
		System.out.println(5/(double)2);
		System.out.println(123/10);
		System.out.println(0.1+0.2);
		System.out.println(5%-2);
		System.out.println(-3%2);
		System.out.println(123%10);
		System.out.println(123.2%1);
		
		byte b = 10;
		byte c = 12;
		byte sum = (byte)(b+c);
		System.out.println(sum);
		
		int x1 = 10;
		float x2 = 2.5F;
		float sum2 = x1+x2;
		System.out.println(sum2);
		
		int i = 1;
		int a = ++i;
		System.out.println(i);
		System.out.println(a);
		
		//习题
		int j = 1;
		//int sum3 = ++j + j++;
		int y1 = ++j;//j=2 y1=2
		int y2 = j++;//j=3 y2=2
		int sum3 = y1+y2;//4
		System.out.println(j);
		System.out.println(sum3);
		
		int aa = 1;
		aa = aa++;
		aa = aa++;
		aa = aa++;
		System.out.println(aa);
	}

}

 

1简单赋值运算符(普通赋值运算符):=

1)可以连续赋值

2)可以参与运算

2.复合赋值运算符:+=,-=,*=,/=,%=

short a = 1;

a += 2;//a变为3

a+=2与a=a+2并不完全一样,a+=2里边存在一个隐式的类型转换

相当于a=(a的类型)(a+2),结果是+=左边的类型

public class OperatorDemo02 {
	
	public static void main(String[] args) {
		int a = 10;
		int x1,x2,x3;
		x1 = x2 = x3 = 20;
		//两值交换
		int x = 1;
		int y = 13;
		
		//方式一
//		int z = x;
//		x = y;
//		y = z;
		//方式二
		x = x+y;//x=14
		y = x-y;//1
		x = x-y;//13
		System.out.println(x);
		System.out.println(y);
		
		int num1 = 3;
		int num2 = 5;
		num2 = (num1+num2) - (num1=num2);
		System.out.println(num1);
		System.out.println(num2);
		
		short score = 90;
		score += 5;
		//score = (short)(score+5);
		System.out.println(score);
		
	}

}

关系运算符

>,<,>=,<=,==(等于),!=(不等于)。结果为布尔类型

public class OperatorDemo03 {

	public static void main(String[] args) {
		int score = 9;
		System.out.print(score>=60);
	}

}

逻辑运算符

与,或,非

与:并且,如果两个条件同时为true,则结果为true &&:短路与,如果第一个条件为false,则不会判断第二个条件 &:非短路与,即使第一个条件为false,也会判断第二个条件

或,或者,如果有一个条件为true,则结果为true ||:短路或:如果第一个条件为true,则不会判断第二个条件 |:非短路或:即使第一个条件为true,也会判断第二个条件

非:取反,true变false,false变true !

public class OperatorDemo04 {

	public static void main(String[] args) {
		int score = 800;
		System.out.println(score >= 0 && score <= 100);

		int a = 1;
		System.out.println(a < 0 & a++ > 0);
		System.out.println(a);
		// 年龄40岁以下可以入职,或者性别是女可以入职
		int age = 50;
		String gender = "女";
		System.out.println(age < 40 || gender == "女");
		
		boolean ok = true;
		System.out.println(!ok);
	}

}

条件运算符

?:

布尔类型表达式?结果为true则执行此部分:否则执行此部分

嵌套条件运算符:在问号或者冒号部分还有条件运算符

public class OperatorDemo05 {

	public static void main(String[] args) {
//		int score = 8;
//		String result = score>=60 ? "及格" : "不及格";
//		System.out.println(result);

		// >=90 A >=60B <60 C
		int score = 98;
		String result = score >= 90 ? "A" : score >= 60 ? "B" : "C";
		System.out.println(result);

		// 求a,b,c的最大值
		int a = 50;
		int b = 20;
		int c = 22;

		// 方式一
//		int max;
//		max = a > b ? a : b;
//		max = max > c ? max : c;
//		System.out.println(max);

		// 方式二
		int max;
		max = (a > b ? a : b) > c ? (a > b ? a : b) : c;
		System.out.println(max);

	}
}

【按操作数划分】

一元运算符(单目运算符):只有一个操作数,如:a++,-1

二元运算符(双目运算符):有两个操作数,如:a+b

三元运算符(三目运算符):有三个操作数,即?:

流程控制

分支语句

if,switch

if:

一、单分支

if(条件){

//如果条件为true,则执行此部分代码

}

int score = 90;
		if(score>=60){
			System.out.println("及格");
		}

 

二、双分支

if(条件){

//如果条件为true,则执行此部分代码

}else{

//否则执行此部分代码

}

当代码块语句是一句,执行语句时,{}可以省略不写。

if

代码块;

else

代码块;

 

int score = 90;
		if(score>=60) {
			System.out.println("及格");
		}else
			System.out.println("不及格");

 

三、多分支

if(条件1){

//如果条件1为true,则执行此部分代码,不会判断下面的条件

}else if(条件2){

//如果条件2为true,则执行此部分代码,不会判断下面的条件

}...

else{

//如果以上条件都不满足,则执行此部分代码

}

四、嵌套分支:在if,else if,else部分还有分支语句

//>=90 优秀		>=80良好		>=60中等		<60差
		int score = 800;
		if(!(score<0 || score>100)) {
			if(score>=90) {
				System.out.println("优秀");
			}else if(score>=80) {
				System.out.println("良好");
			}else if(score>=60) {
				System.out.println("中等");
			}else {
				System.out.println("差");
			}
		}else {
			System.out.println("不合法");
		}

 

switch:开关语句

switch(变量){

case 值1:

//如果变量和值1相等,则执行此部分代码

break;

...

case 值n:

//如果变量和值n相等,则执行此部分代码

break;

default:

//如果变量和以上值都不相等,则执行此部分代码

}

注意:

1.case贯穿:如果没有break,会继续执行,直到遇见一个break或者程序结束

2.case后面必须是一个具体的值,不能是变量,也不能是多个值,也不能表示范围

3.case的值不能重复

4.swich支持的6种类型:byte,short,int,char,String(Java 7) ,枚举(Java 5)

快捷键

万能键:alt+/(?),main=>主方法

复制:ctrl+c

粘贴:ctrl+v

剪切:ctrl+x

撤回:ctrl+z

删除一行:ctrl+d

保存:ctrl+s

单行注释:ctrl+/(?)

多行注释:ctrl+shift+/

变成大写:ctrl+shift+x

变成小写:ctrl+shift+y

循环

1.while循环 2.for循环 3.do-while循环 4.新型for循环

【while循环】

while(条件){

循环体

}

确定循环次数

1.初始变量

while(2.循环条件){

3.循环体

4.迭代因子

}

执行顺序:1234 234 234...

 

public static void main(String[] args) {
//		int i = 1;
//		while(i<=2) {
//			System.out.println("跑了"+i+"圈");
//			i++;
//		}

		// 创建一个未知次数的循环
		Scanner sc = new Scanner(System.in);
		System.out.println("是否继续?Y/N");
		String answer = sc.next();
		while ("Y".equals(answer)) {
			System.out.println("欢迎使用");
			// 编写代码

			System.out.println("是否继续?Y/N");
			answer = sc.next();
		}
		System.out.println("程序结束");

	}

【for循环】

for(1.初始变量;2.循环条件;4.迭代因子){

3.循环体

}

执行顺序:1234 234 234...

【应用场景】

1.while循环适合不确定循环次数的场景

2.for循环适合确定循环次数的场景

for(int i=1;i<=2;i++) {
			System.out.println("跑了"+i+"圈");
		}

 

【循环控制】

1.break:终止整个循环

2.continue:终止本次循环,还会执行下次循环

【do while】

1.初始变量

do{

3.循环体

4.迭代因子

}while(2.循环条件);

执行顺序:1342 342 342 ....

do while循环至少执行一次

int i = 1;
		do {
			System.out.println("跑了"+i+"圈");
			i++;
		}while(i<=2);

嵌套循环

/*
		 * 	嵌套循环 
		 * *** 
		 * *** 
		 * ***
		 */
		for(int j=1;j<=3;j++) {
			for(int i=1;i<=3;i++) {
				System.out.print("*");
			}
			System.out.println();
		}

1.迭代算法:是指不断由已知的条件推出新值的过程

/*
		 * 	迭代算法:是指不断由已知的条件推出新值的过程
		 * 	斐波那契数列:1 1 2 3 5 8 13 21...个数由输入决定
		 * 				a  b c
		 * 				   a b c
		 * 					 a b c
		 * 	c = a+b;
		 * 	a = b;
		 * 	b = c;
		 */
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int a = 1;
		int b = 1;
		int c;
		for(int i = 1;i<=n;i++) {
			System.out.print(a+" ");
			c = a+b;
			a = b;
			b = c;
		}

穷举算法:是指遍历一个域穷尽其范围内的所有可能性

/*
		 * 	穷举算法:是指遍历一个域穷尽其范围内的所有可能性
		 * 	例子:有一个未知数,这个数除以三余二,除以五余三,除以七余二,问你这个数是多少
		 */
		for(int i=1;;i++) {
			if(i%3==2 && i%5==3 && i%7==2) {
				System.out.println(i);
				break;
			}
		}

随机数

1.Math.random()生成0~1之间的随机小数

生成随机数[min,max) =>(int)(Math.random*(max-min)+min);

2.Random类

Random rand = new Random();

rand.nextInt(上限),生成0到上限-1之间的随机整数。[0,上限)

生成随机数[min,max) =>rand.nextInt(max-min)+min;

public static void main(String[] args) {
		/*
		 * 随机数 Math.random():生成0~1之间的随机小数
		 * 
		 * [0,10)随机整数:(int)(Math.random()*10)
		 * 
		 * 产生随机数[min,max) =》 (int)(Math.random()*(max-min)+min)
		 * 
		 */
		// [1,100) [0,99)+1
		System.out.println((int) (Math.random() * 99 + 1));

		// [50,80) [0,30)+50
		System.out.println((int) (Math.random() * 30 + 50));

		// 随机生成小写字母 a:97 z:122  A:65 Z:90
		// [0,26)
		System.out.println((char) (Math.random() * 26 + 'a'));
		System.out.println((char) (Math.random() * 26 + 97));

		// 随机生成字母(不区分大小写)  
//		int num = (int) (Math.random() * 52);// [0,52)
//		if (num < 26) {// [0,26)
//			System.out.println((char) (num + 'a'));
//		} else {//[26,52)
//			System.out.println((char)(num-26 + 'A'));
//		}
		
		//随机生成字母(不区分大小写)或数字(0~9)
//		int num = (int)(Math.random()*62);
//		if(num<10) {
//			System.out.println(num);
//		}else if(num<36) {//[10,36)
//			System.out.println((char)(num-10+'a'));
//		}else {//[36,62)
//			System.out.println((char)(num-36+'A'));
//		}
		
		/*
		 * Random类
		 * Random rand = new Random();
		 * rand.nextInt(上限),[0,上限) 整数
		 */
		Random rand = new Random();
		System.out.println(rand.nextInt(10));
		//[1,10) [0,9)+1
		System.out.println(rand.nextInt(9)+1);
		
		
	}

数组

1.声明数组:数据类型[] 数组名;

数据类型 数组名[];不推荐

2.实例化数组:数组名 = new 数据类型[长度];

1+2=>3.声明并实例化数组:数据类型[] 数组名 = new 数据类型[长度];

注意:数组长度是int类型

4.使用数组:

1)为元素赋值:数组名[索引] = 值;

索引,下标,角标,下角标,从0开始,最大索引比长度小1

2)获取元素值:数组名[索引];

5.数组长度:数组名.length

public static void main(String[] args) {
//		int[] scores;
//		scores = new int[3];
		int[] scores = new int[4];
		scores[0] = 90;
		scores[1] = 89;
		scores[2] = 88;
		scores[3] = 60;
		
        //遍历数组
        //方式一
//		for(int i=0;i<scores.length;i++) {
//			System.out.println(scores[i]);
//		}
		/*
		 * 	新型for循环,增强for循环,foreach循环,迭代循环,for冒号循环
		 * 	for(元素的数据类型 变量名 : 数组名){
		 * 		//每次循环,变量的值,就是数组中的每一个元素
		 * 	}
		 */
        //方式二
		for(int score : scores) {
			System.out.println(score);
		}
	}

6.数组默认值

整数类型:0

byte:(byte)0

short:(short)0

int:0

long:0L

浮点类型:

float:0.0F

double:0.0

字符类型:char \u0000,实际就是0

布尔类型:false

字符串:null

7.数组初始化

1)数据类型[] 数组名 = new 数据类型[]{元素1,元素2,...};

2)数据类型[] 数组名 = {元素1,元素2,...};此方式只能在声明数组时使用

public static void main(String[] args) {
//		int[] scores = new int[] { 90, 88, 76, 66 };
		int[] scores = { 90, 88, 76, 66 };
		//错误
//		int[] scores;
//		scores = { 90, 88, 76, 66 };
		
        for (int score : scores) {
			System.out.println(score);
		}
	}

ArrayIndexOutOfBoundsException 下标越界异常

冒泡排序

// 冒泡排序
	public static void main(String[] args) {
		// 小→大
		int[] arr = { 25, 16, 7, 51, 65, 78, 91, 1 };// 8个数
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = 0; j < arr.length - 1 - i; j++) {
				// 交换
				if (arr[j] > arr[j + 1]) {
					int temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				}
			}
		}
		System.out.println(Arrays.toString(arr));
	}

数组排序:Arrays.sort(数组名);默认是正序排序

数组转字符串:Arrays.toString(数组名);

数组扩容/缩容:Arrays.copyOf(数组名 , 新长度);

扩容:新长度比原长度大

缩容:新长度比原长度小

数组克隆:数组名.clone();

Arrays.copyOf(数组名 , 原长度);

比较两个数组是否相等:Arrays.equals(num1,num2);

二分查找法:Arrays.binarySearch(); 前提是有序数组

public static void main(String[] args) {
//		int[] arr = { 15, 17, 28, 39, 40, 51, 57 };
//		Scanner sc = new Scanner(System.in);
//		int num = sc.nextInt();
//		boolean flag = false;
//		// 查找数组下标最小值
//		int min = 0;
//		// 查找数组下标最大值
//		int max = arr.length - 1;
//		// 当最小值小于等于最大值
//		while (min <= max) {
//			// 寻找中间值
//			int m = (min + max) / 2;
//			if (num == arr[m]) {
//				System.out.println("找到了");
//				flag = true;
//				break;
//			} else if (num > arr[m]) {
//				min = m + 1;
//			} else {
//				max = m - 1;
//			}
//		}
//		if(!flag) {
//			System.out.println("没有");
//		}

		/*
		 * 二分查找法:Arrays.binarySearch(),前提是有序数组
		 */
//		int[] arr = { 15, 17, 28, 39, 40, 51, 57 };
//		Scanner sc = new Scanner(System.in);
//		System.out.println("输入一个数:");
//		int n = sc.nextInt();
//		int index = Arrays.binarySearch(arr, n);
//		if (index >= 0 && index <= arr.length - 1) {
//			System.out.println("找到了");
//			System.out.println(index);
//		} else {
//			System.out.println("没有");
//		}

		Scanner sc = new Scanner(System.in);
		int[] nums = { 1, 5, 8, 2 };
		System.out.println("输入一个数:");
		int num = sc.nextInt();
		boolean flag = false;
		for (int i = 0; i < nums.length; i++) {
			if (num == nums[i]) {
				System.out.println("找到了");
				flag = true;
				break;
			}
		}
		if (!flag) {
			System.out.println("木有");
		}

	}

二维锯齿数组

数据类型 [] [] 数组名 = new 数据类型 [长度] [长度]

int[] [] nums = new int[2] [3];

nums[0] [0] nums[0] [1] nums[0] [2]

nums[1] [0] nums[1] [1] nums[1] [2]

nums是一个数组,里面有2个元素,长度是2

nums[0]也是一个数组,里面有3个元素,长度是3

nums[1]也是一个数组,里面有3个元素,长度是3

public static void main(String[] args) {
//		int[][] nums = new int[2][3];
//		//第一行
//		nums[0][0] = 1;
//		nums[0][1] = 2;
//		nums[0][2] = 3;
//		//第二行
//		nums[1][0] = 4;
//		nums[1][1] = 5;
//		nums[1][2] = 6;
//		System.out.println(nums.length);
//		System.out.println(nums[0].length);
//		System.out.println(nums[1].length);
		
//		int[][] nums = new int[2][];
//		nums[0] = new int[3];
//		nums[1] = new int[2];
		
		int[][] nums = new int[][] {{1,2,3},{4,5,6,7}};
		int[][] nums2 = new int[][] {{1,2,3},{4,5,6,7}};
		
		//遍历数组
		for(int i=0; i < nums.length; i++) {
			for(int j=0; j < nums[i].length; j++) {
				System.out.print(nums[i][j] +  " ");
			}
			System.out.println();
		}
		
		System.out.println(Arrays.deepToString(nums));
		System.out.println(Arrays.deepEquals(nums, nums2));
	}

面向对象

面向过程:是具体化的,流程化的,解决一个问题,你需要一步一步的分析,一步一步的实现。

注重的是具体实现过程,每个步骤亲力亲为

例:吃饺子=》和面,和馅,包,蒸,吃...自己弄

面向对象:是模型化的,注重的对象与对象之间的协作,不必去一步一步的实现

例:点外卖,商家做,骑手送,自己吃

面向对象优点:

优点:易维护,易复用,易扩展

类:是一种抽象的表示,可以把具有相同特征的事物归为一类,例如:人类,车类,鸟类...

对象:类别中具体的一个事物

对象的成员:

1.属性:指对象的特征

2.方法:指对象的动作(行为)

定义类

访问修饰符 class 类名{

}

定义方法

访问修饰符 返回值类型 方法名(参数列表){

方法体

}

1.无参数无返回值类型

访问修饰符 void 方法名(){

方法体

}

2.有参数无返回值类型

访问修饰符 void 方法名(参数列表){

方法体

}

3.无参数有返回值类型

访问修饰符 返回值类型 方法名(){

方法体

}

4.有返回值类型有参数

访问修饰符 返回值类型 方法名(参数列表){

方法体

}

参数列表:方法中需要数据时,但它本身没有,需要从外部传入,就要定义参数

形参:形式参数,在方法定义时写的参数

实参:实际参数,在方法调用时传入的参数

返回值:外部需要方法内部数据时,需要返回值

1.在定义方法时,需要指定返回值类型

2.在方法体中,使用return关键字,返回一个具体的值

方法重载:方法名相同,参数列表不同(参数的个数不同,参数类型不同)

方法签名:方法名+参数列表

可变长参数/不定长参数:数据类型... 变量名 注意:可变长参数必须是最后一个参数

成员变量(字段,域) 成员变量默认值: 整数类型:0

byte:(byte)0

short:(short)0

int:0 long:0L

浮点类型:0.0

float:0.0F

double:0.0

字符类型:0

布尔类型:false

类类型:null

成员变量和局部变量的区别:**
      1.作用域不同:
          局部变量的作用域仅局限于定义它的方法
          成员变量的作用域在整个类内部都是可见的,还可以在外部访问
      2.初始值不同:
          Java会给成员变量一个初始值
          Java不会给局部变量一个初始值
      3.在同一个方法中,不允许有同名局部变量
         在不同的方法中,可以有同名局部变量
      4.两类变量同名时,局部变量具有更高的优先级

 

面向对象三大特征:封装,继承,多态

封装

1.定义一个方法是一种封装

2.成员变量或者方法用private修饰是一种封装

属性组成部分:属性变量和属性访问器

属性变量:用于表示属性的成员变量

属性访问器:setter和getter

属性名:setter和getter去掉set和get后,剩下部分首字母小写

只读属性:只有getter没有setter

public class Student {
	private int score;
	// 赋值方法 setter (set访问器)
	public void setScore(int score) {
		//this:本类对象
		this.score = score;
	}

	// 取值方法 getter (get访问器)
	public int getScore() {
		return score;
	}
}

 

构造器(构造方法)

没有返回值,名称和类名相同

构造方法是在实例化对象时自动调用

默认构造方法:

1.如果不创建构造方法,也有一个默认构造方法

2.默认构造方法没有参数

3.如果创建了有参构造方法,则默认构造方法消失

在构造器中调用本类其他构造器:this(参数)

this()必须写在构造器的第一行代码上

静态方法(类方法)

是属于类的,不属于对象,使用类调用

静态方法不能直接调用成员方法,也不能直接使用成员变量

静态方法不能使用this

成员方法可以调用静态方法,也可以使用静态变量

静态块/静态代码块

static{}

在第一次使用类的时候自动调用,而且只调用一次

静态块的执行要优先于主方法的执行

静态块和静态方法的区别:

1.静态块自动调用,静态方法手动调用

2.静态块只调用一次,静态方法可以调用多次

3.静态块没有访问修饰符,返回值类型,名称,参数,静态方法有

动态块:{},实例化对象时自动调用

JVM内存

栈,堆,方法区

栈:

栈帧:JVM为每一个方法都定义一个栈帧,栈帧中存放局部变量

堆:实例化出来的对象,成员变量

方法区:静态变量,方法信息

继承

减少代码冗余,实现代码重用性

访问修饰符 class 子类 extends 父类{

}

子类又叫派生类

父类又叫超类,基类

单继承:子类只能继承一个父类,如Java

多继承:子类可以继承多个父类,如C++

子类可以继承父类非私有成员(同包)

继承中的构造器:

1.先调用父类构造器,再调用子类构造器

2.子类默认调用父类的无参构造器

3.构造器不能继承

4.子类调用父类构造器:super(参数),super()必须写在构造器的第一行代码上

5.如果父类没有无参构造器,则子类必须手动调用父类的其他构造器

super:父类的

super.属性 父类的属性

super.方法(参数) 父类的方法

super(参数列表) 父类的构造方法,必须放在第一行

this:本类对象

this.属性 当前对象属性

this.方法() 当前对象的方法

this(参数列表) 当前构造方法,必须放在第一行

【访问修饰符】  

本类本包其他类其他包子类其他包
public共有的
protected保护的
默认的
private私有的

重写

重写:子类重新写父类的方法

一大两小两相同

两相同:方法名相同,参数列表相同

一大:访问修饰符要大于等于父类的

两小:1)返回值类型要小于等于父类, 如果是基本类型或者void,必须保持一致

2)抛出异常的类型要小于等于父类的

不能重写的方法:

构造器不能重写

私有方法不能重写

静态方法不能重写

final修饰的方法不能重写

重写和重载的不同点及相同点:

重载和重写重写(override)重载(overload)
作用域子重写父的是同一作用域(子重载父的,重载自己)
方法名必须一致必须一致
参数列表必须一致必须不一致(个数不同,类型不同)
返回值类型返回值类型要小于等于父类的,如果是基本类型或者void,必须保持一致无所谓
访问修饰符子大于等于父类无所谓
异常抛出异常的类型要小于等于父类的无所谓
次数一次多次

向上造型(向上转型):子类型赋值给父类型

向下造型:父类型赋值给子类型(可以会出现类型转换异常)

多态

同一种行为,产生的结果不同

满足多态的条件:继承,重写,向上造型

面向对象三大特征:封装,继承,多态

面向对象四大特征:封装,继承,多态,抽象

final

final:最终,不可变的

final修饰类,不能被继承

final修饰方法,不能被重写

对于方法和类,abstract和final不能连用

final修饰成员变量,不能被重复赋值。可以在定义时赋值,也可以在构造器和动态块中赋值

常量:用final修饰。命名规范:所有字母都大写,每个单词之间用下划线隔开(尖叫式蛇底命名法)

final修饰局部变量

对于基本类型来说,变量中的数据不可改变

对于引用类型来说,变量中的地址值不可改变

final修饰参数,不可以赋值,值是通过方法调用传过来的,在方法内部不能改值

抽象

抽象类:类上用abstract修饰

抽象方法:方法上用abstract修饰,没有方法体

抽象类不能实例化对象

抽象类可以有抽象方法,也可以有非抽象方法

抽象方法要写在抽象类里

如果子类不是抽象类,则必须实现父类的抽象方法

如果子类也是抽象类,则可以不实现父类的抽象方法

private和abstract不能连用

final和abstract不能连用

接口

是一种公共的规范标准,引用数据类型

定义接口:

访问修饰符 interface 接口名{

}

1.在默认情况下,接口中的方法都是公有抽象方法(public abstract)

2.接口不能实例化对象

3.接口中没有构造器

4.接口中的变量,都是公有静态常量(public static final修饰)

5.在Java8中,提供了接口的默认方法(default)和静态方法

6.在Java9中,提供了接口的私有方法(private)

7.定义一个实现接口的语法:implements实现

访问修饰符 class 类名 implements 接口名1,接口2,...{

}

8.定义一个接口继承接口的语法:extends继承

访问修饰符 interface 接口名 extends 接口1,接口2...{

}

9.在Java中,类是单继承,接口是多实现,多继承。

10.实现类既可以继承父类,又可以实现接口

访问修饰符 class 类名 extends 父类 implements 接口名1,接口名2,...{

}

11.抽象类和接口

             抽象类                                        接口
定义关键字abstract classinterface
继承关系单继承多继承
构造方法
实例化对象不能不能
普通成员可以不能有变量,普通方法是jdk1.8之后可以
与接口的关系多实现【implements】多继承【extends】


 

内部类

静态内部类,动态内部类,局部内部类,匿名内部类

静态内部类

访问修饰符 class 外部类{

访问修饰符 static class 内部类{

}

}

public class Outer {
	private static int n = 1;
	public static class Inner {
		private int n = 2;
		public void show() {
			int n = 3;
			System.out.println(Outer.n + "," + this.n + "," + n);
		}
	}

	public void display() {
		Inner inner = new Inner();
		inner.show();
	}

}

在外部访问静态内部类: 外部类.内部类 变量 = new 外部类.内部类();

Outer.Inner inner = new Outer.Inner();
		inner.show();

动态内部类

访问修饰符 class 外部类{

class 内部类{

}

}

public class Outer {
	private int n = 1;

	public class Inner {
		private int n = 2;

		public void show() {
			int n = 3;
			System.out.println(Outer.this.n + "," + this.n + "," + n);
		}
	}

	public void display() {
		Inner inner = new Inner();
		inner.show();
	}

}

在外部访问动态内部类

外部类 变量 = new 外部类();

外部类.内部类 变量 = 外部类变量.new 内部类();

Outer outer = new Outer();
		Outer.Inner inner = outer.new Inner();
		inner.show();

 局部内部类

public class Demo {
	
	public static void main(String[] args) {
		//局部内部类
		class Inner{
			public void show() {
				System.out.println("show");
			}
		}
		Inner inner = new Inner();
		inner.show();
	}

}

匿名内部类

public static void main(String[] args) {
		/*
		 * 	匿名内部类
		 * 	类名 变量 = new 类名(){};
		 */
		Human h = new Human() {

			@Override
			public void work() {
				System.out.println("工作");
			}
			
		};
		
		h.work();
	}

类能用什么访问修饰符修饰

1.对于外部类,只能用public和默认

2.对于内部类:

1)如果是静态内部类和动态内部类:四种都可以

2)如果是局部内部类和匿名内部类:不可以写

常用类

String字符串

java.lang.String 包下

程序中所有的双引号字符串,都是String类的对象(就算没有new,也是)

charAt():依据索引查找字符

compareTo():字符串比较,正数:第一个串大,负数:第二个串大,0:相等

compareToIgnoreCase():不区分大小写比较,正数:第一个串大,负数:第二个串大,0:相等

concat():拼接字符串

contains():判断是否存在

startsWith():判断是否以某子串开头

endsWith():判断是否以某子串结尾

equals():判断字符串相等

equalsIgnoreCase():不区分大小写判断字符串相等

getBytes():将字符串转成字节数组

indexOf():依据元素查找索引(第一次出现)

lastIndexOf():依据元素查找索引(最后一次出现)

isEmpty():判断是否是空串

length():字符串长度

replace():字符串替换

split():字符串分割,返回值类型为字符串数组。注意:如果遇到分割时出现错误,需要将分隔符用\转义

substring():截取子串,不包含结束位置,含头不含尾。字符串.substring(开始位置),从开始位置截取 到最后

toCharArray():字符串转char类型数组

toLowerCase():转成小写

toUpperCase():转成大写

trim():去掉左右两边空格

字符串常量池

字符串常量池:程序中直接写上的双引号字符串,就在字符串常量池中

对于基本数据类型,==是进行数值的比较

对于引用数据类型,==是进行地址的比较

地址相同的情况: 情况1: String str1 = "abc"; String str2 = "abc"; 情况2: String s1 = "abc"; String s2 = "ab" + "c"; 地址不相同的情况: 情况1: String s1 = "abc"; String s = "c"; String s2 = "ab" + s; 情况2: String ss1 = new String("abc"); String ss2 = new String("abc");

StringBuilder,StringBuffer

专门用于字符串拼接的,拼接时不生成新的对象,拼接速度快

String,StringBuilder,StringBuffer的区别:

1.String是常量,值不能改变,拼接字符串时生成新的对象,拼接速度慢

StringBuilder,StringBuffer是动态拼接,拼接时不生成新的对象,拼接速度快

2.StringBuider,StringBuffer提供了更多的方法,如插入,删除

3.StringBuilder是线程不安全的,拼接速度快

StringBuffer是线程安全的,拼接速度慢

public static void main(String[] args) {
		StringBuilder s = new StringBuilder();
		//添加字符串
		s.append("ab");
		s.append("hello");
		System.out.println(s);
		// 插入字符串
		s.insert(1, "q");
		System.out.println(s);
		// 删除字符串,含头不含尾
		s.delete(1, 4);
		System.out.println(s);
		
		StringBuilder s2 = new StringBuilder("abcd");
		//字符串反转
		System.out.println(s2.reverse());
	}

包装类型

包装类型:每一个基本类型,都对应着一个类,他将基本类型封装到类中,添加了额外的功能,还可以赋值为null

基本类型包装类型父类型
byteByteNumber
shortShortNumber
intIntegerNumber
longLongNumber
floatFloatNumber
doubleDoubleNumber
charCharacterObject
booleanBooleanObject

装箱:基本类型转换成包装类型的过程

拆箱:包装类型转换成基本类型的过程

  • 【手动拆装箱】

  • Java 5之前

  • 手动装箱:将基本类型写在包装类型的构造器中。Integer a1 = new Integer(200);

  • 手动拆箱:包装类型变量.xxxValue(); int a2 = a1.intValue();

  • 【自动拆装箱】

  • 自动装箱:包装类型 变量 = 基本类型值; Integer num = 200;

  • 自动拆箱:基本类型 变量 = 包装类型变量

  • 【自动拆装箱的注意事项】

  • 赋值时,要求严格对应上类型。如:

  • Long a = 10L;

  • Double b = 2D;

  • 包装类型比较用equals方法

  • 【整型池】

  • 整型缓存池,整型常量池

  • 范围:-128~127

  • Integer i1 = 128;

  • Integer i2 = 128;

  • System.out.println(i1 >= i2);//true

  • 首先将两个包装类型自动拆箱成基本类型,然后比较基本类型的值

  • 类型转换:

  • 包装类型.parse类型(字符串); 返回基本类型

  • 包装类型.value Of(字符串); 返回包装类型

  • 最大值:MAX_VALUE

  • 最小值:MIN_VALUE

  • 位数:SIZE

DoubelTest

NaN:Not a Number NaN和任何一个数都不相等,包括它自己 Double.isNaN(数值):判断是否是NaN Double.NaN:0.0d / 0.0 Infinity:正无穷 -Infinity:负无穷 Double.POSITIVE_INFINITY:1.0 / 0.0 Double.NEGATIVE_INFINITY:-1.0 / 0.0

CharacterTest

public static void main(String[] args) {
		char c = ' ';
		// 判断是否是整数
		System.out.println(c >= '0' && c <= '9');
		System.out.println(Character.isDigit(c));
		// 判断是否是小写字母
		System.out.println(c >= 'a' && c <= 'z');
		System.out.println(Character.isLowerCase(c));
		// 判断是否是大写字母
		System.out.println(c >= 'A' && c <= 'Z');
		System.out.println(Character.isUpperCase(c));
		// 判断是否是字母
		System.out.println((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
		System.out.println(Character.isLetter(c));
		// 判断是否字母或数字
		System.out.println((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')||(c >= '0' && c <= '9'));
		System.out.println(Character.isLetterOrDigit(c));
		//判断是否是空白字符(空格,Tab,回车,换行)
		System.out.println(Character.isWhitespace(c));
	}

正则表达式

Java是从Java1.4开始支持正则表达式

正则表达式,简写为regex,regexp,regxp等

是用于匹配、查找、替换文本等操作的表达式

正则表达式包含普通字符和元字符

元字符就是一类特殊字符,有具体的含义:

^、$:开始和结束

[abc]:匹配abc中任意字符

[ ^abc]:除了abc的任意字符

[a-z]:a到z之间的字符

[a-zA-Z0-9]:a到z、A到Z、0到9之间的任意字符

\d :数字字符,等效于[0-9]

\w :单词字符,等效于[ a-zA-Z0-9_ ]

\s :空白字符,如空格,制表符,换行,回车等。

\D :非数字字符

\W:非单词字符

\S :非空白字符

?:0到1个

*:0到多个

+:1到多个

.:任意字符

|:或者

\:转译

X{n}:n个X

X{n,}:n到多个X

X{n,m}:n到m个X

^:非

():分组

public static void main(String[] args) {
		String str = "中国";
		//验证是否是整数
		boolean ok = str.matches("^\\d+$");
		System.out.println(ok);
		//验证是否是小数
		boolean ok2 = str.matches("^\\d+\\.\\d+$");
		System.out.println(ok2);
		//验证两位小数
		boolean ok3 = str.matches("^\\d+\\.\\d{2}$");
		System.out.println(ok3);
		//验证整数或者小数
		boolean ok4 = str.matches("^\\d+(\\.\\d+)?$");
		System.out.println(ok4);
		//验证大多数汉字:\u4E00 \u9FA5
		boolean ok5 = str.matches("^[\u4E00-\u9FA5]+$");
		System.out.println(ok5);
		
	}
public static void main(String[] args) {
		String str = "abc123def456wer";
		//str = str.replace("123", "-");
		str = str.replaceAll("\\d+", "-");
		System.out.println(str);
		
		String str2 = "Java.Python.PHP";
		String[] ss = str2.split("\\.");
		System.out.println(Arrays.toString(ss));
	}
public static void main(String[] args) {
//		String str = "Java123Python456";
//		// 模式对象,设置正则表达式
//		Pattern p = Pattern.compile("[a-zA-Z]+");
//		// 匹配对象,匹配字符串
//		Matcher m = p.matcher(str);
//		// 判断有没有找到匹配上的字符串
//		while(m.find()) {
//			System.out.println(m.group());//匹配上的字符串
//		}
		
		String str = "name=tom;salary=¥$18000;";
		Pattern p = Pattern.compile("(\\w+)=([^;]+)");
		Matcher m = p.matcher(str);
		while (m.find()) {
			//m.group(组索引),从1开始
			System.out.println(m.group(1) + "\t" + m.group(2));
		}

Object

Object是所有类的父类,又叫顶级父类,也叫万类之源

如果一个类没有指定父类,默认继承了Object

除了Object之外,剩下的所有类都有父类

Object中有一些方法,有时需要重写

如:toString(),默认是返回类全名@哈希值

一般用作返回类中信息(成员变量的值),所以需要重写

对于print和println,如果传入了类类型变量,就是调用了toString方法

equals(),equals方法是Object中的方法,默认是判断地址相等(==)

但是建议你重写equals(),用于比较值相对

(比如String,在String类中定义了equals能够比较值相对,是因为String中重写了equals方法)

Math

Math.max():最大值

Math.min():最小值

Math.round():四舍五入

Math.ceil():向上取整

Math.floor():向下取整

Math.pow():求幂

Math.sqrt():开平方

Math.cbrt():开立方

Math.abs():绝对值

Math.PI():π

日期类

date

Date date = new Date();

调用了System.currentTimeMillis()

Date date = new Date(毫秒数);传入系统毫秒数

date.getTime():获取系统毫秒数

date.setTime():设置系统毫秒数

date2.compareTo(date):日期比较,返回值:正数:第一个日期大,负数:第二个日期大,0:相同

date2.after(date):判断日期是否是另一个日期之后

date2.before(date):判断日期是否是另一个日期之前

SimpleDateFormat,简单日期格式,用来做日期的格式化

格式化字符:

y:年(yyyy:四位年及以上;yy:两位年)

M:月(MM:两位月)

d:日(dd:两位日期)

h:12进制小时(hh:两位小时)

H:24进制小时(HH:两位小时)

m:分钟

s:秒

S:毫秒

E:星期

a:上午/下午

X,Z:时区

如果想要直接显示字母,需要加上单引号

public static void main(String[] args){
		Date date = new Date();
		// System.out.println(date);
		// 如果向直接显示字母,需要加上单引号
		SimpleDateFormat fmt = new SimpleDateFormat("yyyy年MM月dd日  'at' HH:mm:ss:SS");
		// Date对象转格式化字符串
		String str = fmt.format(date);
		System.out.println(str);
		// 格式化字符串转Date对象,字符串和日期格式不一致时,日期转换异常:ParseException
		//Date date2 = fmt.parse(str);
		Date date2 = fmt.parse(str, new ParsePosition(0));
		System.out.println(date2);

	}

Calendar

格里高利历(公历,阳历,GregorianCalendar)

获取年份:cal.get(Calendar.YEAR)

获取月份,月份从0开始,所以真实月份需要加1:cal.get(Calendar.MONTH)+1

获取日期:cal.get(Calendar.DATE)

cal.get(Calendar.DAY_OF_MONTH)

获取小时(12进制):cal.get(Calendar.HOUR)

获取小时(24进制):cal.get(Calendar.HOUR_OF_DAY)

获取分钟:cal.get(Calendar.MINUTE)

获取秒:cal.get(Calendar.SECOND)

获取毫秒:cal.get(Calendar.MILLISECOND)

获取星期,星期从1开始,星期日是1,所以需要减1:cal.get(Calendar.DAY_OF_WEEK) - 1

public static void main(String[] args) {
		Calendar cal = Calendar.getInstance();
		System.out.println(cal);
//		System.out.println(cal.getClass());
//		Calendar cal2 = new GregorianCalendar();
//		System.out.println(cal2);
		// 获取年份:
		System.out.println(cal.get(Calendar.YEAR));
		// 获取月份:月份从0开始,所以真实月份需要加1
		System.out.println(cal.get(Calendar.MONTH) + 1);
		// 获取日期
		System.out.println(cal.get(Calendar.DATE));
		System.out.println(cal.get(Calendar.DAY_OF_MONTH));
		// 获取小时(12进制)
		System.out.println(cal.get(Calendar.HOUR));
		// 获取小时(24进制)
		System.out.println(cal.get(Calendar.HOUR_OF_DAY));
		// 获取分钟
		System.out.println(cal.get(Calendar.MINUTE));
		// 获取秒
		System.out.println(cal.get(Calendar.SECOND));
		// 获取毫秒
		System.out.println(cal.get(Calendar.MILLISECOND));
		// 获取星期,星期从1开始,星期日是1,所以需要减1
		System.out.println(cal.get(Calendar.DAY_OF_WEEK) - 1);

	}
public static void main(String[] args) {
		Calendar cal = Calendar.getInstance();
		//获取Date对象
		Date date = cal.getTime();
		SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
		System.out.println(fmt.format(date));
		
		Calendar cal2 = Calendar.getInstance();
		// 将date对象传到Calendar中
		cal2.setTime(date);
		System.out.println(cal.get(Calendar.YEAR));
		
		
		// 获取系统毫秒数
		System.out.println(cal.getTimeInMillis());
		// 设置系统毫秒数
		cal.setTimeInMillis(123456L);
	}

设置字段:cal.set(字段常量,值);

设置年:cal.set(Calendar.YEAR, 2018);

设置月:cal.set(Calendar.MONTH, 10-1);

设置日期:cal.set(Calendar.DATE, 30);

设置年月日:cal.set(2017, 10-1, 30);

添加字段的值:cal.add(字段的常量, 值)

滚动字段的值:cal.roll(字段的常量, 值)

add和roll的区别:

add:如果超出本字段的范围,会影响到上一个字段

roll :如果超出本字段的范围,不会影响到上一个字段,

会在本字段中循环滚动

获取最大值:cal.getActualMaximum()

获取最大值:cal.getMaximum()

getActualMaximum和getMaximum的区别:

getActualMaximum跟当前字段的值有关

getMaximum跟当前字段的值无关,只是获取本字段的最大值

当前日期是当前年份的第几天:cal.get(Calendar.DAY_OF_YEAR);

补充

instanceof:判断左边的对象是否是右边的实例,结果是boolean,是返回true,不是返回false

包:主要是用来对类进行整理的,将同种类型的类放在同一个包中。com.zretc.javase.d0831

声明包语法:package 包名; 只能有一条,且必须放在有效代码第一行

导包:当使用的类不在同一个包中时,需要导包

导包的语法:import 包名.类名; 导包可以有多条,且必须放在声明包下面,定义类上面

单类导入:import 包名.类名;

多类导入:import 包名.*;

泛型

泛型:参数化的类型

泛型:泛型方法,泛型类

泛型:不支持基本类型,不能实例化对象

Java中的泛型,是Java5增加的特征

擦除法泛型,Java的泛型是语法层面的,编译之后,泛型类型是Object

在Java7 之前:类名<泛型类型> 变量 = new 类名<泛型类型> ();

在Java7 及之后版本:类名<泛型类型> 变量 = new 类名<> ();

泛型:只能是类类型的,可以把类类型当成参数来传递

泛型方法:

访问修饰符 < T> 返回值类型 方法名(参数列表){}

public class MyArrayUtil {

	public static <T> T[] add(T[] arr, T value) {
		arr = Arrays.copyOf(arr, arr.length + 1);
		arr[arr.length - 1] = value;
		return arr;
	}
	
	public static Object add2(Object[] nums,Object value) {
		nums = Arrays.copyOf(nums, nums.length+1);
		nums[nums.length-1] = value;
		return nums;
	}

}

 

泛型类:

访问符 class 类名< T>{}

泛型限定:

访问修饰符 class 类名<T extends 父类>{}

public class MyArrayUtil02<T extends Number> {
	
	Object[] nums = new Object[0];
	
	public void add(T value) {
		nums = Arrays.copyOf(nums, nums.length + 1);
		nums[nums.length - 1] = value;
	}

	@Override
	public String toString() {
		return Arrays.toString(nums);
	}

}
public static void main(String[] args) {
		MyArrayUtil02<Integer> myArray = new MyArrayUtil02<>();
		myArray.add(10);
		myArray.add(20);
		System.out.println(myArray);
	}

集合

List是Collection的子接口,主要存储有序可重复数据

ArrayList:数组列表,使用数组实现

添加元素:list.add();

插入元素:list.add(索引,元素);

修改元素:list.set(索引,元素);

删除元素(依据元素删除):list.remove(元素);

删除元素(依据索引删除):list.remove(索引);

如果泛型类型是Integer,使用remove时,传入元素,会当成索引,所以需要将元素强制转换成Integer或Object。

获取元素:list.get(索引);

集合长度:list.size();

清空集合:list.clear();

遍历集合三种方式:

public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
		list.add(3306);
		list.add(1433);
		list.add(1521);
		// 遍历集合 
		// 方式一,使用普通for循环
		for(int i=0;i<list.size();i++) {
			System.out.println(list.get(i));
		}
		System.out.println("===============");
		// 方式二,使用增强for循环
		for(Integer a : list) {
			System.out.println(a);
		}
        System.out.println("==============");
		// 方式三,使用迭代器
		// 获取迭代器
		Iterator<Integer> it = list.iterator();
		// 判断有没有下一条数据
		while(it.hasNext()) {
			// 移动到下一条,并获取数据
			System.out.println(it.next());
		}
	}

 

Collections:集合工具类

Collections.addAll(集合,元素,元素,...):向集合中添加若干元素

判断是否有某子串:list.contains()

依据元素查找索引(从左到右):list.indexOf()

依据元素查找索引(从右向左):list.lastIndexOf()

判断集合是否为空:list.isEmpty()

获取子集合(含头不含尾):

实际上是从集合中获取一部分,但是还是同一个集合,一个修改,会影响另一个

如果想互不影响,需要将list.subList()放到List集合的实现类的构造器里

List<Integer> sub = new ArrayList<>(list.subList(1, 3));

Collection和Collections的区别

Collection是集合的总接口,是存储单一类型的集合

Collections是集合工具类,提供操作集合的相关方法

数组转List:

Arrays.asList():转成了只读集合

正确做法:将Arrays.asList()放在List实现类的构造器里

List<泛型类型> 变量 = new ArrayList<>(Arrays.asList(数组));

Integer[] nums = { 1, 2, 3 };
		List<Integer> list = new ArrayList<>(Arrays.asList(nums));
		list.add(0, 10);
		System.out.println(list);

 

List转数组:

方式一:类型[] 数组 = list.toArray(new 类型[0])

方式二:类型[] 数组 = new 类型[集合长度]

list.toArray(数组)

// 方式一
		// Integer[] arr = list.toArray(new Integer[0]);
		// 方式二
		Integer[] arr = new Integer[list.size()];
		list.toArray(arr);
		// 输出arr数组
		System.out.println(Arrays.toString(arr));

 集合排序

public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
		Collections.addAll(list, 3306, 1433, 1521);
		// 正序排序
		// Collections.sort(list);
		
		/*
		 * 	正序排序:第一个数减第二个数
		 * 	叙排序:第二个数减第一个数
		 */
		
//		Collections.sort(list, new Comparator<Integer>() {
//
//			@Override
//			public int compare(Integer o1, Integer o2) {
//				return o2 - o1;
//			}
//			
//		});
//		
//		System.out.println(list);
		
		list.sort(new Comparator<Integer>() {

			@Override
			public int compare(Integer o1, Integer o2) {
				return o1 - o2;
			}
		});
		System.out.println(list);
		
	}

ArrayList和LinkedList的区别:

  1. ArrayList是用数组实现的,在内存中是连续的,适合遍历和追加

  2. LinkedList是用链表实现的,在内存中不是连续的,适合插入和删除

    LinkedList能够实现队列和栈

    队列:先进先出(FIFO)

    栈:先进后出(FILO)

Queue<类型> queue = new LinkedList<>();

添加元素:queue.offer();

获取元素(不删除):queue.peek();

获取元素并删除:queue.poll();

public static void main(String[] args) {
		Queue<Integer> queue = new LinkedList<>();
		// 添加元素
		queue.offer(10);
		queue.offer(20);
		queue.offer(30);
		System.out.println(queue);
		// 获取元素(不删除)
		System.out.println(queue.peek());
		System.out.println(queue.peek());
		System.out.println("==============");
		for (Integer num : queue) {
			System.out.println(num);
		}
		System.out.println("==============");
		// 获取元素并删除
		System.out.println(queue.poll());
		System.out.println(queue.poll());
		System.out.println(queue.poll());
   }

 

Deque<类型> stack = new LinkedList<>();

进栈:stack.push();

出栈:stack.pop():

public static void main(String[] args) {
		Deque<Integer> stack = new LinkedList<>();
		// 进栈
		stack.push(10);
		stack.push(20);
		stack.push(30);
		System.out.println(stack);
		System.out.println("============");
		for (Integer n : stack) {
			System.out.println(n);
		}
		System.out.println("============");
		while(stack.size()>0) {
			System.out.println(stack.pop());
		}
		System.out.println("============");
		// 出栈
//		System.out.println(stack.pop());
//		System.out.println(stack.pop());
//		System.out.println(stack.pop());
	}

 

Set是Collection的子接口,无序存储,不可重复存储,可以存储null值

HashSet:无序的

添加元素:add()

依据元素删除:remove(元素)

获取长度:size()

遍历Set集合

for (String string : phone) {
			System.out.println(string);
		}

 

Set集合转成List集合,放到List实现类的构造器中

List集合转Set集合,放到Set集合实现类的构造器中

public static void main(String[] args) {
		Set<String> phone = new HashSet<>();
		phone.add("13312345688");
		phone.add("13912345688");
		phone.add("13612345688");
		// Set转成List,放到List实现类的构造器中
		List<String> list = new ArrayList<>(phone);
		list.add(1,"12212345678");
		list.add("13612345688");
		System.out.println(list);
		
		// List转Set,放到Set集合实现类的构造器中
		Set<String> set = new HashSet<>(list);
		System.out.println(set);
	}

 

HashSet:无序的

LinkedHashSet:添加的顺序

TreeSet:排序的(默认按照正序排序)

public static void main(String[] args) {
		// 倒叙排序,将比较器放在TreeSet的构造器中
		Set<String>  phone = new TreeSet<>(new Comparator<String>() {

			@Override
			public int compare(String o1, String o2) {
				return o2.compareTo(o1);
			}
		});
		phone.add("13312345688");
		phone.add("13912345688");
		phone.add("13612345688");
		System.out.println(phone);
	}

 

Map以键值对的形式存在,键是不能重复的,值是可以重复的

HashMap:无序的

LinkedHashMap:添加的顺序

TreeMap:排序的(默认按照键的正序排序)

添加:put(键,值)

修改:put()

删除(依据键删除):remove(键)

是否包含某键:containsKey()

获取集合长度:size()

获取键集合:keySet()

获取值集合:values()

依据键获取值:get(键)

清空集合:clear()

遍历Map集合:

public static void main(String[] args) {
		Map<String, String> map = new HashMap<>();
		map.put("name", "高斯林");
		map.put("gender", "男");
		map.put("job", "构架师");

		// 遍历Map集合方式一:通过遍历键集合
		for (String str : map.keySet()) {
			System.out.println(str + "\t" + map.get(str));
		}
		
		System.out.println("================");
		/*
		 * 	遍历Map集合方式二:通过遍历键值对对象
		 * 	Entry:键值对对象
		 * 	entry.getKey():获取键
		 * 	entry.getValue():获取值
		 */
		for (Entry<String, String> entry : map.entrySet()) {
			System.out.println(entry.getKey() + "\t" + entry.getValue());
		}
		// 遍历值
		System.out.println("===========");
		for (String string : map.values()) {
			System.out.println(string);
		}
	}

 

Properties属性集合,键值对都是字符串,可以保持到文件中

添加值:setProperty(键,值)

获取值:getProperty(键)

获取值,如果没有键,就返回默认值:getPropertity(键,默认值);

HashMap和Hashtable的区别

1.HashMap是线程不安全的,速度稍快,推荐使用,赋值可以存放null

2.Hashtable是线程安全的,速度稍慢,不推荐使用,键值不能存放null

异常

语法:

try-catch, try-catch-finally,try-finally

【try-catch】

try{

//可能会出现异常的代码

}catch(异常对象){

//捕捉到异常之后执行的代码

}

Throwable(Java语言中所有错误或异常的父类)

|

|-- Exception(异常)

| |

| |-- 运行时异常(非检查异常),RuntimeException

| | |

| | |-- ArithmeticException(算术异常)

| | |-- NumberFormatException(数字格式异常)

| | |-- NullPointerException(空指针异常)

| | |-- StringIndexOutOfBoundsException(字符串索引越界异常)

| | |-- ArrayIndexOutOfBoundsException(数组索引越界异常)

| | |-- IndexOutOfBoundsException(索引越界异常)

| | |-- ClassCastException(类型转换异常)

| |

| |-- 非运行时异常(编译异常,检查异常),Exception

|

|-- Error(错误)

Exception:程序中出现的异常

Error:一般指虚拟机出现的错误

运行时异常:编写程序和编译程序时不会出现异常,但是运行的时候有可能出现异常

非运行时异常:在编写程序或编译程序时就出现了异常,需要异常处理

catch:可以有多个,但是范围必须由小到大

抛异常:

1.在方法定义时,指定能够抛出哪些异常的类型

2.抛出异常:throw new 异常对象()

自定义异常:可以继承RuntimeException,调用一个父类的有参构造器传递信息

public static void getDate(String s) throws ParseException {
		SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
//		Date date = null;
//		try {
//			 date = fmt.parse(s);
//		} catch (ParseException e) {
//			// e.printStackTrace();
//			System.out.println("出现了日期转换异常");
//		}
		Date date = fmt.parse(s);
		System.out.println(date);
	}
	
	/*
	 * 	重写中:子类重写方法的异常对象要小于等于父类的异常对象
	 * 	父类的方法没有异常,子类重写的方法也不能有异常对象
	 */
	/*
	 * 	抛异常
	 *	1.在方法定义时,指定能够抛出哪些异常的类型
	 *	2.抛出异常:throw new 异常对象()
	 */
	public static void setAge(int age) throws RuntimeException {
		if(age<0) {
			throw new AgeException("年龄错误");
		}
		System.out.println("年龄:"+age);
	}

	public static void main(String[] args) {
		try {
			getDate("2021-01");
		} catch (ParseException e) {
			// e.printStackTrace();
			System.out.println("出现了日期转换异常");
		}
		System.out.println("ok");
		
		try {
			setAge(-60);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		setAge(60);
	}

 

// 自定义异常
public class AgeException extends RuntimeException {
	
	public AgeException(String message) {
		super(message);
	}

}

try:将有可能发生异常的代码放在try里

catch:通过大于等于本身异常进行捕获

finally:无论是否有异常,都会执行(System.exit(0):退出程序除外)

try可以分别和catch,finally连用,也可以三个一起使用

try,catch里有return,finally也会执行,且在return之前执行

 

public static int method() {
		int[] arr = { 1, 2, 3, 4, 5 };
		int j = 9;
		for (int i = 0; i <= arr.length; i++) {
			try {
				System.out.println("当前元素:" + arr[i]);
				j++;//10
				return j;//10
			} catch (RuntimeException e) {
				System.out.println("数组下标越界异常");
			} finally {
				System.out.println("当前下标是:" + i);
				j++;//11
				return j;
			}
		}
		return j;
	}
	
	public static int show() {
		int a = 1;
		try {
			return a++;
		}catch(Exception e) {
			return a++;
		}finally {
			return a++;
		}
	}

	public static void main(String[] args) {
		/*
		 * 	当前元素:1
		 * 	当前下标:0
		 * 	11
		 */
		System.out.println(Test03.method());
		System.out.println(show());//2
//		try {
//			int a = 0 / 0;
//		} catch (Exception e) {
//			System.out.println("出现了异常");
//			System.exit(0);
//		} finally {
//			// 无论是否有异常,都会执行(System.exit(0);//退出程序除外)
//			System.out.println("finally里的代码");
//		}
		
//		try {
//			int a = 0/0;
//		}finally {
//			System.out.println("finally里的代码");
//		}
//		System.out.println("ok");
	}

final,finally,finalize的区别

1.final修饰类不能被继承,修饰方法不能被重写,修饰变量值不能改变

2.finally,在异常处理中,一定能执行的部分(除了System.exit(0))

3.finalize,Object中的方法,在销毁对象之前调用,不建议重写

Java.lang.RuntimeException与java.lang.Exception区别

RuntimeException:这个类出现的异常可以不处理即如果某个异常类型为RuntimeException的子类的话就可以不 用try catch来处理。但Exception这个类的异常就必须使用try catch 来处理异常

File

File在io包中

IO:Input Output,输入输出

文件路径,推荐使用相对路径,不要使用绝对路径(完整的路径,比如d:\a.txt)使用绝对路径不能跨平台

相对路径,是从项目路径开始

判断文件是否存在:file.exists()

创建文件:file.createNewFile()

文件长度:file.length()

文件路径(相对路径):file.getPath()

路径分隔符:/(Unix、Linux的分隔符,Windows也识别)

不要使用\(只有DOs和Windows识别)

获取当前操作系统的分隔符:File.separator

文件路径(绝对路径):file.getAbsolutePath()

设置最后修改时间:setLastModified();

获取最后修改时间:lastModified()

只获取文件名(不包含路径):getName()

获取父级名称:getParent()

设置只读:setReadOnly()

设置是否可写:setWritable()

是否是隐藏文件:isHidden

判断是否是文件:isFile()

判断是否是文件夹(目录):isDirectory()

创建文件夹:mkdirs()

删除文件夹:delete()

获取到文件夹下面的所有文件:file.listFiles()

File[] files = file.listFiles();
		for (File f : files) {
			if(f.isFile()) {
				System.out.print("文件:");
			}else {
				System.out.print("目录:");
			}
			System.out.println(f.getName());
		}
	}

 

IO流

IO流

|

|-- 字节流(适合操作二进制数据)

| |

| |-- InputStream(输入流)

| | |

| | |-- FileInputStream(文件输入流)

| | | |

| | | |-- BufferedInputStream(缓冲输入流)

| | | |-- DataInputStream(数据输入流)

| | |-- ObjectInputStream(对象输入流)

| | |-- ... ...

| |

| |-- OutputStream(输出流)

| |

| |-- FiltOutputStream(文件输出流)

| |-- FilterOutputStream(过滤输出流)

| | |-- BufferedOutputStream(缓冲输入流)

| | |-- DataOutputStream(数据输出流)

| | |-- PrintStream(打印流)

| |-- ObjectOutputStream(对象输出流)

| |-- ... ...

|

|-- 字符流(适合操作文本数据)

|

|-- Reader(读取流)

| |

| |-- InputStreamReader(输入流读取器)

| | |-- FileReader(文件读取器)

| |-- BufferedReader(缓冲读取器)

| |-- ... ...

|

|-- Writer(写入流)

|

|-- OutputStreamWriter(输出流写入器)

| |-- FileWriter(文件写入器)

|-- BufferedWriter(缓冲写入器)

|-- PrintWriter(打印写入器)

|-- ... ...

FileOutputStream:文件输出流,向文件中写入数据

fos.write():向文件中写入数据

字符串.getBytes(编码):将字符串转换成指定编码格式的字节数组

FileOutputStream构造器参数:

文件名,是否追加(默认不追加)

参数2为是否追加,若是true则是追加

public static void main(String[] args) throws IOException {
		/*
		 * FileOutputStream:文件输出流,向文件中写入数据 
		 * FileOutputStream 参数2为是否追加,为true时是追加
		 */
		FileOutputStream fos = new FileOutputStream("f1.txt", true);
		fos.write(97);
		byte[] bs = {65,66,67,68};
		fos.write(bs);
		fos.write(bs, 1, 3);
    	// 换行
		fos.write('\n');
		// 字符串.getBytes(编码):将字符串转成指定编码格式的字节数组
		fos.write("Hello World!".getBytes("UTF-8"));
		fos.close();
	}

 

FileInputStream:文件输入流,从文件中读取数据

fis.read(): 从此输入流中读取一个数据字节

public static void main(String[] args) throws IOException {
		/*
		 * 	文件输入流:FileInputStream:将硬盘中的数据读取到内存中
		 */
		FileInputStream fis = new FileInputStream("f1.txt");
//		int len = fis.read();
//		System.out.println(len); // 97 a
//		
//		len = fis.read();
//		System.out.println(len);// 98 b
//		
//		len = fis.read();
//		System.out.println(len); // 99 c
//		
//		len = fis.read();
//		System.out.println(len); // -1
		
		int len;
		while((len = fis.read()) != -1) {
			System.out.print((char)len);
		}
		fis.close();
	}

 将byte数组转字符串,new String(byte数组, 开始位置, 长度)

public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream("f1.txt");
//		byte[] b1 = new byte[2];
//		int len = fis.read(b1);
//		System.out.println(len); //2
//		System.out.println(new String(b1));
//		
//		byte[] b2 = new byte[2];
//		len = fis.read(b2);
//		System.out.println(len);
//		System.out.println(new String(b2));
//		
//		byte[] b3 = new byte[2];
//		len = fis.read(b3);
//		System.out.println(len);
//		System.out.println(new String(b3));

		byte[] bs = new byte[1024 * 10];// 每次最多能够读取的长度
		int len;// 真实长度
		String str = "";
		// len=fis.read(bs):将数据读取到byte数组中
		while ((len = fis.read(bs)) != -1) {
			// 将byte数组转字符串,new String(byte数组,开始位置,长度)
			str += new String(bs, 0, len);
		}
		fis.close();
		System.out.println(str);
	}

 拷贝

public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		System.out.println("输入源文件:");
		String str = sc.next();
		System.out.println("请输入目标文件:");
		String str2 = sc.next();
		
		FileInputStream fis = new FileInputStream(str);
		FileOutputStream fos = new FileOutputStream(str2);
		byte[] bs = new byte[10240];
		int len;
		while((len=fis.read(bs)) != -1) {
			fos.write(bs);
		}
		fis.close();
		fos.close();
		
		File file = new File(str);
		File file2 = new File(str2);
		file2.setLastModified(file.lastModified());
		
		System.out.println("拷贝成功!!");
	}

BufferedOutputStream,BufferedInputStream:缓冲流

低级流,节点流:直接操作硬件设备的流,比如FileOutputStream

高级流,处理流:不直接操作硬件设备,需要传入一个流来进行操作,比如BufferedOutputStream

public static void main(String[] args) throws IOException {
		// write();

		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("f2.txt"));
		byte[] bs = new byte[10240];
		int len;
		String str = "";
		while ((len = bis.read(bs)) != -1) {
			str += new String(bs, 0, len);
		}
		bis.close();
		System.out.println(str);
	}
	// Ctrl+1
	private static void write() throws FileNotFoundException, IOException {
		// 缓冲流
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("f2.txt"));
		byte[] bs = { 97, 98, 99, 100 };
		bos.write(bs, 0, 2);
		bos.write('\n');
		bos.write("hello".getBytes());
		bos.close();
	}

DateOutputStream,DataInputStream:数据流,高级流

public class DataStream {

	public static void main(String[] args) throws IOException {
		write();
		// 数据流 高级流
		DataInputStream dis = new DataInputStream(new FileInputStream("f3.txt"));
		System.out.println(dis.readInt());
		System.out.println(dis.readUTF());
		System.out.println(dis.readDouble());
		dis.close();
		
	}

	private static void write() throws FileNotFoundException, IOException {
		DataOutputStream dos = new DataOutputStream(new FileOutputStream("f3.txt"));
		dos.writeInt(100);
		dos.writeUTF("Hello World!");
		dos.writeDouble(3.14);
		dos.close();
	}

}

ObjectOutputStream,ObjectInputStream:对象流,高级流

ObjectOutputStream:将对象转成byte数组

ObjectInputStream:将byte数组转成对象

序列化:将对象转成byte数组、字符串等。

反序列化:将byte数组、字符串等转成对象。

// 若想进行二进制序列化,实现Serializable(可序列化接口)
public class Emp implements Serializable{

	private String name;
	private double salary;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "Emp [name=" + name + ", salary=" + salary + "]";
	}

}

 

public class ObjectStream {

	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
		// write();
		
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("emp.txt"));
		// 数据写入到对象中(反序列化的过程)
		Emp emp = (Emp) ois.readObject();
		ois.close();
		System.out.println(emp);
	}

	private static void write() throws IOException, FileNotFoundException {
		// 对象流,高级流
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("emp.txt"));
		Emp emp = new Emp();
		emp.setName("tom");
		emp.setSalary(18000);
		// 对象写入到流中(序列化的过程)
		oos.writeObject(emp);
		oos.close();
	}

}

PrintStream:打印流

public static void main(String[] args) throws FileNotFoundException {
		//打印流
//		PrintStream ps = new PrintStream("p.txt");
//		ps.println("Hello Java");
//		ps.print("hell");
//		ps.close();
		
		//System.out.println();
		PrintStream ps = new PrintStream(System.out);
		ps.println("hello");
	}

 

字符流

FileWriter FileReader,文件读写,低级流(节点流)

public static void main(String[] args) throws IOException {
		FileWriter fw = new FileWriter("w1.txt");
		fw.write(97);
		char[] cs = { '你', '好', '你', '是', '小', '丑' };
		fw.write(cs);
		fw.write(cs, 0, 2);// 写入的开始位置和写入的长度
		fw.write("helloworld", 2, 3);
		fw.write("高斯林\n");
		fw.write("埃里森");
		fw.close();

		FileReader reader = new FileReader("w1.txt");
		char[] c = new char[10240];
		int len;
		String str = "";
		while ((len = reader.read(c)) != -1) {
			str += new String(c, 0, len);
		}
		reader.close();
		System.out.println(str);

	}

 

BufferedWriter,BufferedReader,缓冲读写流,高级流

PrintWriter,打印写入器

	public static void main(String[] args) throws FileNotFoundException {
		PrintWriter out = new PrintWriter("p.txt");
		out.println(100);
		out.println("Hello World");
		out.close();
		
		Scanner sc = new Scanner(new File("p.txt"));
		System.out.println(Integer.parseInt(sc.nextLine()));
		//sc.nextLine();
		System.out.println(sc.nextLine());
	}

多线程

并发:指两个或多个事件在同一个时间段内发生

并行:指两个或多个时间在同一时刻发生(同时发生)

线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少

有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程

程序。 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程。

线程调度:

分时调度: 所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。

抢占式调度: 优先让优先级高的线程使用 CPU,如果线程的优先级相同,

那么会随机选择一个(线程随机性),Java使用的为 抢占式调度。

主线程:执行主(main)方法的线程

单线程程序:java程序中只有一个线程

创建多线程程序的方式一:

java.lang.Thread类:是描述线程的类

实现步骤:

1.创建一个Thread类的子类(继承Thread类)

2.重写run方法,设置线程的任务

3.创建Thread类的子类对象

4.调用Thread类中的start方法,开启新的线程,执行run方法

 

// 1. 创建一个Thread类的子类
public class MyThread extends Thread {
	// 2.在Thread类的子类中重写Thread类中的run方法,设置线程任务

	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			System.out.println("run:" + i);
		}
	}
}

 

public static void main(String[] args) {
		
		// 3. 创建Thread类的子类对象
		MyThread mt = new MyThread();
		// 4.调用Thread类中的start方法,开启新的线程,执行run方法
        // start的方法一个线程只能调用一次
		mt.start();
		
		for (int i = 0; i < 20; i++) {
			System.out.println("main:" + i);
		}
	}

 

获取线程名称:

  • 1.使用Thread类中的方法getName()

    String getName():返回该线程的名称

  • 2.可以先获取到当前正在执行的线程,使用线程中的方法getName()获取线程的名称

    static Thread currentThread()返回当前正在执行的线程对象的引用

public class MyThread_getName extends Thread{

	@Override
	public void run() {
 
	}
}

 

public static void main(String[] args) {
		MyThread_getName mt = new MyThread_getName();
		mt.start();// Thread-0
		
		new MyThread_getName().start();// Thread-1
		new MyThread_getName().start();// Thread-2
		// 获取主线程名称 main
		System.out.println(Thread.currentThread().getName());
	}

设置线程名称:

public class Thread01 {

	public static void main(String[] args) {
		MyThread_getName mt = new MyThread_getName();
		mt.start();// Thread-0
		
		new MyThread_getName().start();// Thread-1
		new MyThread_getName().start();// Thread-2
		// 获取主线程名称 main
		System.out.println(Thread.currentThread().getName());
	}

}
public static void main(String[] args) {
//		MyThread_setName mt = new MyThread_setName();
//		// 设置线程名称
//		mt.setName("王昊");
//		mt.start();
		
		// 设置线程名称
		new MyThread_setName("旺财").start();
	}

sleep:让程序睡眠

public static void sleep(long millis)

式当前正在执行的线程以指定的毫秒数暂停,毫秒数结束后,线程继续执行

public static void main(String[] args) {
		// 模拟秒表
		for (int i = 1; i <= 60; i++) {
			System.out.println(i);
			try {
				// Thread 类的sleep方法让程序睡眠1秒钟
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

 

创建多线程程序的方式二:

1.实现Runnable接口

2.重写run方法

3.创建一个Runnable接口的实现类对象

4.创建Thread对象,构造方法中传递Runnable接口的实现类对象

5.调用Thread类中的start方法,开启新的线程

// 1.创建一个Runnable接口的实现类
public class RunnableImpl implements Runnable {

	// 2. 在实现类中重写Runnable接口的run方法,设置线程任务
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			System.out.println(Thread.currentThread().getName() + "-->" + i);
		}
	}
}

 

public static void main(String[] args) {
		// 3. 创建一个Runnable接口的实现类对象
		RunnableImpl run = new RunnableImpl();
		// 4. 创建Thread类对象,构造方法中传递Runnable接口的实现类对象
		Thread t = new Thread(run);
		// 5.调用Thread类中的start方法,开启新的线程
		t.start();
		
		for (int i = 0; i < 20; i++) {
			System.out.println(Thread.currentThread().getName() + "-->" + i);
		}
	}

第一种方式:使用简单,但是影响子类继承其他类

第二种方式:不影响继承,降低了程序的耦合度(解耦)

线程安全问题

解决线程安全问题:

方式一:使用同步代码块

格式:synchronized(锁对象){

可能会出现线程安全问题的代码(访问了共享数据的代码)

}

注意:

1. 通过代码块中的锁对象,可以使用任意的对象

2. 但是必须保证多个线性使用的锁对象是同一个

3. 把同步代码块锁住,只让一个线程在同步代码块中执行

public class TicketThread implements Runnable {

	private int ticket = 100;

	// 创建一个锁对象
	Object obj = new Object();

	// 卖票
	@Override
	public void run() {
		while (true) {
			synchronized (obj) {
				// 判断票是否存在
				if (ticket > 0) {
					// 票存在 ticket--
					System.out.println(Thread.currentThread().getName() + "=>正在卖第" + ticket + "张票");
					ticket--;
				}
			}
		}
	}
}
public static void main(String[] args) {
		TicketThread t = new TicketThread();
		Thread t0 = new Thread(t);
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		t0.start();
		t1.start();
		t2.start();
	}

方式二:使用同步方法

使用步骤:1.把访问了共享数据的代码抽取出来,放到一个方法中

2.在方法上添加synchronized修饰符

格式:

访问修饰符 synchronized 返回值类型 方法名(参数列表){

可能会出现线程安全问题的代码(访问了共享数据的代码)

}

public class TicketThread implements Runnable {

	// 定义一个多个线程共享的票源
	private int ticket = 100;

	@Override
	public void run() {
		while(true) {
			payTicket();
		}
	}

	public synchronized void payTicket() {
		if (ticket > 0) {
			System.out.println(Thread.currentThread().getName() + "=>正在卖第" + ticket + "张票");
			ticket--;
		}
	}
}

 

public static void main(String[] args) {
		TicketThread t = new TicketThread();
		Thread t0 = new Thread(t);
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		t0.start();
		t1.start();
		t2.start();
	}

同步:顺序执行(A,B,C,D 接力赛)

异步:同时执行(A,B,C,D 比赛)

死锁:多个线程访问共同资源,且处于互相等待的状态,会导致死锁

sleep让当前线程处于休眠状态,但是不释放资源

wait让当前线程处于等待状态,释放资源,但是需要通过notify/notifyAll进行唤醒

线程的五种状态(线程生命周期)

1.新建状态:线程被建立

2.就绪状态:将新建的线程,加入到执行队列中

3.运行状态:线程被执行

4.阻塞状态:执行过程中发生了等待状态,导致线程暂停

5.消亡状态:线程结束

23种设计模式

单例模式:只有一个实例

1.构造方法要私有化

2.设置一个公共的静态方法返回当前类对象

饿汉模式:事先创建好对象

懒汉模式:使用时才会创建

public class Earth {
	// 懒汉模式:使用时才会创建
//	private static Earth earth;
//	
//	private Earth() {
//		System.out.println("创建对象");
//	}
//	
//	public static Earth getEarth() {
//		if(earth == null) {
//			return earth = new Earth();	
//		}
//		return earth;
//		
//	}
	// 饿汉模式:事先创建好对象
	private static Earth earth = new Earth();

	private Earth() {
		System.out.println("创建对象");
	}

	public static Earth getEarth() {
		return earth;
	}

}

 

public static void main(String[] args) {
		Earth e1 = Earth.getEarth();
		Earth e2 = Earth.getEarth();
		System.out.println(e1 == e2);// true
	}

工厂模式:工厂里有n个管理类,同一由工厂来产生对象

枚举:将可以选择的数据,一一列出,只能选择给你列出来的数据

比如:在杨洋,邓论,李现,王嘉尔中输入你喜欢的男明星

补充:

面向对象之间的关系:

1.继承(泛化):类与类之间的关系就叫做继承。(Cat 继承 Animal)

2.实现:类与接口之间的关系。(Bird 实现 Fly接口)

3.依赖:一个必须用到另一个。(演奏者演奏乐器的前提得给一个乐器)

4.关联:一个里边有另一个。

聚合:关系不是特别强烈的,可有可无的是聚合。(Person中有一个属性是Card)

组合:关系比较强烈的,必须有的,叫做组合。(Person中有Body)

is a(继承,实现) use a(依赖) has a(关联)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烜烜程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值