JavaSE
1,明确需求。我要做什么?
2,分析思路。我要怎么做?1,2,3。
3,确定步骤。每一个思路部分用到哪些语句,方法,和对象。
4,代码实现。用具体的java语言代码把思路体现出来。
学习新技术的四点:
1,该技术是什么?
2,该技术有什么特点(使用注意):
3,该技术怎么使用。demo
4,该技术什么时候用?test。
JavaSE笔记
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程序的最小单位
基本windows的DOS命令:
打开DOS命令窗口:
开始菜单-->运行-->输入cmd-->回车【快捷键:Windows+R】
常见的命令:
exit:退出当前命令窗口
cls:清屏
dir:列出当前目录下所有的子文件/子目录
del *class:删除class文件
cd ..:回到上一级
cd \:直接回到根目录
c: d: e: 回车 切换盘符
第一个Java程序
创建项目:File→New(Other)→Java Project →Project name →Finish →no
创建包:src右键→new→Package→Name→Finish
创建类:在包上右键→New→Class→Name→Finish
注释
// :单行注释
/**/:多行注释
/** */:文档注释
注意:这种注释是比较专业的注释,它会被javadoc.exe工具解析提取并生成帮助文档。
输出语句
-
不换行输出:System.out.print("");
-
换行输出:System.out.println("");
转义字符\
双引号:"
单引号:'
反斜线:\
制表符:\t(Tab键,适合不对齐的输出)
换行:\n
第一个Java程序
public 公共的 class类 static 静态的 void 没有返回值(空)
main 方法名 String 字符串
(String[] args(可以自己起))是一个main方法的参数列表
System系统 out输出 println打印并换行
//定义包
package cn.etc.java.d0810;
//定义类,类名要和文件名必须一致,类体中不可以直接编写Java语句,声明变量除外
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");
}
}
public class 和class的区别:
一个java源文件当中可以定义多个class
一个java源文件当中public的class不是必须的
一个class会定义生成一个xxx.class字节码文件 一个java源文件当中定义公开的类的话,只能有一个,并且该类名称必须和java源文件名称一致。
每一个class当中都可以编写main方法,都可以设定程序的入口,想执行B.class中的main方法: java B, 想执行x.class当中的main方法:java x
注意: 当在命令窗口中执行java Hello,那么要求Bello.class当中必须有主方法。没有主方法会出现运阶段的错误: D:l courseavaProjects\02-JavasE\day02>java Hello
错误:在类B中找不到主方法,请将主方法定义为:
public static void main (string[]args)
JAVA和JAVAC命令的作用
JAVAC:作用是JAVA编译器将.java文件编译生成.class字节码文件
JAVA:java命令作用是指JAVA解释器用于将.class字节码文件解释并执行
数据类型
作用:指在jvm运行程序的时候给该数据分配多大的内存空间
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
字符类型 如:'a'(使用单引号)
char 字符型 2个字节 16位 范围:0~65535(\u0000~\uffff)
布尔类型
boolean 布尔型 1或4个字节 8或32位 值:true false
字节(byte):
1 Byte = 8 bit 1KB = 1024 Byte
1 MB = 1024 KB 1KB = 1024 MB
1 TB = 1024 GB
1 TB = 1024 * 1024 * 1024 *1024 * 8
最大值:2的7次方 - 1 = 127
最小值:-128
取值范围:【-128 ~ 127】
byte可以表示256个不同的二进制数字
2.引用数据类型
类类型(class)
字符串(String):多个字符组成了字符串,用引号表示,如“高斯林”,属于类类型(对象)
数组类型(array)
接口类型(interface)
枚举类型(enum)
注解类型(annotation)
变量
java中在使用数据之前,必须要先声明
变量:程序中可以改变的量
变量的三大要素(三大组成部分)
数据类型 变量名 变量值
1.声明变量:数据类型 变量名; 如:short age;
2.变量赋值:变量名 = 值;如:age = 18;
3.声明变量并赋值:数据类型 变量名 = 值; double score = 98.5;
4.声明多个同一类型的变量:数据类型 变量名1,变量名2...
5.访问一个变量有两种方式:
(1)读取变量中保存的具体数据 get/获取
(2)修改变量中保存的具体数据 set/设置
变量名的建议规范
变量名遵循驼峰命名法,即首字母小写,其后每个单词首字母大写
不建议使用汉字,尽量使用英文单词或拼音,要见名知意
不建议使用单个字母命名,约定俗成除外
不建议以下划线开头,不建议使用$
命名法:
驼峰命名法: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类型的方法
基本类型转字符串:
""+基本类型变量或者数值
2、小容量向大容量转换,称为自动类型转换,容量从小到大排序:
byte < short < int < long< f1oat < doubie<char 注意: 任何浮点类型不管占用多少个字节,都比整数型容量大。 char和short可表示的种类数量相同,但是char可以取更大的正整数
3、大容量转换成小容量,叫做强制类型转换,需要加强制类型转换符,程序才能编译通过,但是在运行阶段可能会损失精度,所以谨慎使用。
4、当整数字面值没有超出byte, short , char的取值范围,可以直接赋值给byte , short ,char类型的变量。
5、byte ,short, char混合运算的时候,各自先转换成int类型再做运算。6、多种数据类型混合运算,先转换成容量 最大的那种类型再做运算。
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则是偶数,若结果为非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),结果是+=左边的类型
重要结论:扩展类的赋值运算符不改变运算结果类型,假设最初这个变量的类型是byte类型,无论怎么进行追加或追减,最终该变量的数据类型还是byte类型。
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);
}
}
关系运算符
>,<,>=,<=,==(等于),!=(不等于)。结果为布尔类型:true/false
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 !
异或:两边的算子只要不一样,结果就是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);
}
}
条件运算符
布尔表达式 ? 表达式1 : 表达式2
布尔类型表达式 ? 结果为true执行此部分 : 结果为false时执行此部分
嵌套条件运算符:在问号或者冒号部分还有条件运算符
执行原理:
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
1.分支语句:if
一、单分支
if(布尔表达式) {
//如果条件为true,则执行此部分代码 }
int score = 90;
if(score>=60){
system.out. print1n("及格");
}
二、双分支
if(布尔表达式){
//如果条件为true,则执行此部分代码}else{
//否则执行此部分代码
}
当代码块语句是一句,执行语句时,登可以省略不写。
if
代码块;
else
代码块;
int score = 90;
if(score>=60) {
system. out.print1n("及格");
}else
system.out.print7n("不及格");
三、多分支
if(条件1) {
//如果条件1为true,则执行此部分代码,不会判断下面的条件
}else
if(条件2){
//如果条件2为true,则执行此部分代码,不会判断下面的条件 }...
else{
//如果以上条件都不满足,则执行此部分代码
}
四、嵌套分支:
在if, else if, else部分还有分支语句
//>=90优秀 >=80良好 >=60中等 <60差
int score = 800;
if(! (score<O ll score>100)) {
if(score>=90) {
system. out.print7n("优秀");
}else if(score>=80) {
system. out. println("良好");
}else if(score>=60) {
system.out.print1n("中等");
}else f
system.out. print1n("差");
}
}else i
system.out. print1n("不合法");
}
重点:对于Java中的if语句来说,只要有一个分支执行,整个if语句全部结束。
注意:嵌套时要保证格式完美。
if语句分支中只有一条语句时,大括号可以省略(不推荐)
2.开关语句: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)
思路:
1.选择所有数据从键盘输入
2.使用switch语句进行判断
3.需要从控制台输入三次:
(1) 第一个数字
(2)运算符
(3)第二个数字
循环结构:for,while,do..while
1.while循环 2.for循环 3.do-while循环 4.新型for循环
【while循环】
while(条件){
循环体
}
确定循环次数
1.初始变量
while(2.循环条件){
3.循环体
4.迭代因子
}
执行顺序:1234 234 234...
1、while循环的语法结构:
while(布尔老达式){
循环体; }
2、while循环的执行原理:
先判断布尔表达式的结果:
true
执行循环体
判断布尔表达式的结果:
false
循环结束
3、while循环的循环次数:
0~n次
注意:while循环的循环体可能执行次数为0。
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(初始化表达式;布尔表达式;更新表达式){
//是需要重复执行的代码片段【循环体:由java语句构成】 }
for循环的执行过程/执行原理?
初始化表达式、布尔表达式、更新表达式都不是必须的!【但是两个分号是必须的】
初始化表达式最先执行,并且在整个for循环当中只执行一次。
布尔表达式必须是true/false,不能是其它值。
for的执行过程:
先执行初始化表达式,并且该表达式只执行一次
判断布尔表达式的结果是true还是false
布尔表达式true
执行循环体
执行更新表达式
判断布尔表达式的结果是true还是false
布尔表达式false
循环结束
for(int i=1;i<=2;i++) {
System.out.println("跑了"+i+"圈");
}
【do while】
1、do . .while循环的语法结构:
do{ 循环体; }while(布尔表达式);
2、do . .while循环的执行原理
3、do . .while循环的执行次数: do ..while循环的循环体代码片段执行次数是:1-N次【至少一次】
4、使用do ..while循环的注意事项: 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;
}
}
break:终止整个循环
1、break是java语言当中的关键字,被翻译为"中断/折断”
2、break + ";”可以成为一个单独的完整的java语句: break ;
3、break语句使用在switch语句当中,用来终止switch的语句执行。
4、 break语句同样可以使用在循环语句当中,用来终止循环的执行。
5、break终止哪个循环呢?
6、break;语句使用在for,while , do ..while循环语句当中用来跳出循环,终止循环的执行 因为当程序循环到某个条件的时候,后续的循环没必要执行了,再执行也是耗费资源,所以可以终止循环,这样可以提高程序的执行效率。
continue语句:
continue:终止本次循环,还会执行下次循环
1、continue表示:继续/go on/下一个
2、continue也是一个continue关键字加一个分号构成一个单独的完整的java语句,主要出现循环语句当中用来控制循环的执行。
3、break和continue的区别?
break表示循环不执行了,跳出循环,终止循环。 continue表示终止当前"本次"循环,直接进入下一次循环继续执行。
4、continue也有这样的语法: continue循环名称;【作为了解内容】
随机数
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);
}
字符串
public static void main(String[] args) {
//String简介
String str = "hello!!";
String str2 = "world";
System.out.println(str.equals(str2));
System.out.println(str.equals("hello"));
//长度:字符串.length()
System.out.println(str.length());
}
数组
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 类名{
}
定义方法
访问修饰符 返回值类型 方法名(参数列表){
方法体
return 返回值;
}
1.无参数无返回值类型
访问修饰符 void 方法名(){
方法体
}
2.有参数无返回值类型
访问修饰符 void 方法名(参数列表){
方法体
}
3.无参数有返回值类型
访问修饰符 返回值类型 方法名(){
方法体
return 返回值;
}
4.有返回值类型有参数
访问修饰符 返回值类型 方法名(参数列表){
方法体
return 返回值;
}
参数列表:方法中需要数据时,但它本身没有,需要从外部传入,就要定义参数
形参:形式参数,在方法定义时写的参数
实参:实际参数,在方法调用时传入的参数
返回值:外部需要方法内部数据时,需要返回值
1.在定义方法时,需要指定返回值类型
2.在方法体中,使用return关键字,返回一个具体的值
重载的定义:
1、在同一个类中
2、方法名相同,参数列表不同
3、和返回值、访问修饰符没关系
方法重载:方法名相同,参数列表不同(参数的个数不同,参数类型不同)
方法签名:方法名+参数列表
可变长参数/不定长参数:数据类型... 变量名 注意:可变长参数必须是最后一个参数
成员变量(字段,域) 成员变量默认值: 整数类型: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、基本数据类型:
基本数据类型作为形式参数,形参的改变不会影响实际参数,传递的是值本身
public class Demo {
public static void main(String[] args) {
Dome d = new Dome();
int x = 10;
System.out.println("前:"+x);
d.memo(x);
System.out.println("后:"+x);
}
}
class Dome{
public void memo(int x) {
x += 5;
System.out.println("哦:"+x);
}
}
结果为:
前:10
哦:15
后:10
2、引用数据类型:
引用数据类型作为参数,形参的改变改变影响实际参数,传递的是地址值
public class Demo {
public static void main(String[] args) {
Student d = new Student();
d.name = "小明";
d.age = 22;
System.out.println("前" + d.name + d.age);
Dome t = new Dome();
t.memo(d);
System.out.println("后"+d.name + d.age);
}
}
class Dome{
public void memo(Student x) {
x.name = "小张";
x.age = 18;
System.out.println("1:"+x.name + x.age);
}
}
class Student{
String name;
int age;
}
结果:
前:小明22
1:小张18
后:小张18
匿名对象:
new 对象名();
new 对象名().方法名(new 对象名());
特点:对象只会被调用一次
封装(private)
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、这个字段/数据我要限制用户输入的值,比如说这个字段是sex性别,只能输入男和女,超出了这个范围 就没有 数据,所以我们要限制用户输入的内容,这个时候就使用封装 4、就是只提供这个数据可以给用户外界使用,但不能修改它,此时就用到的封装
构造器(构造方法)
没有返回值,名称和类名相同
构造方法是在实例化对象时自动调用
默认构造方法:
1.如果不创建构造方法,也有一个默认构造方法
2.默认构造方法没有参数
3.如果创建了有参构造方法,则默认构造方法消失
在构造器中调用本类其他构造器:this(参数)
this()必须写在构造器的第一行代码上
无参构造:
访问修饰符 类名(){
}
有参构造:
访问修饰符 类名(参数列表){
方法体
}
一个基本的类应该具备以下特点:
1、成员变量
2、构造方法(有、无参数)
3、成员方法(get/set方法)
静态方法(类方法)
是属于类的,不属于对象,使用类调用
静态方法不能直接调用成员方法,也不能直接使用成员变量
访问静态成员的方法:
类名.成员变量
类名.成员方法
静态方法不能使用this和super
成员方法可以调用静态方法,也可以使用静态变量
static能够修饰的成员有:成员变量、成员方法、修改类、内部类
开发工具类时经常使用static
静态块/静态代码块
static{}
在第一次使用类的时候自动调用,而且只调用一次
静态块的执行要优先于主方法的执行
一般用于初始化静态成员变量
静态块和静态方法的区别:
1.静态块自动调用,静态方法手动调用
2.静态块只调用一次,静态方法可以调用多次
3.静态块没有访问修饰符,返回值类型,名称,参数,静态方法有
动态块:{},实例化对象时自动调用,可以执行多次
1、局部代码宽:定义在局部位置, 作用是限定局部局部变量的作用域
2、构造代码块:定义在类的成员变量的位置,用来抽取多个构造方法重复的代码,做成员变量的初始化
执行顺序:静态代码块 > 动态代码块 > 构造方法
JVM内存:
栈,堆,方法区
栈:
栈帧:JVM为每一个方法都定义一个栈帧,栈帧中存放局部变量
堆:实例化出来的对象,成员变量
方法区:静态变量,方法信息
继承
减少代码冗余,实现代码重用性
访问修饰符 class 子类 extends 父类{
}
子类又叫派生类
父类又叫超类,基类
单继承:子类只能继承一个父类,如Java
多继承:子类可以继承多个父类,如C++
子类可以继承父类非私有成员(同包)
继承中的构造器:
1.先调用父类构造器,再调用子类构造器
2.子类默认调用父类的无参构造器
3.构造器不能继承
4.子类调用父类构造器:super(参数),super()必须写在构造器的第一行代码上
5.如果父类没有无参构造器,则子类必须手动调用父类的其他构造器
super:父类的
super.属性 父类的属性
super.方法(参数) 父类的方法
super(参数列表) 父类的构造方法,必须放在第一行
this:本类对象
this.属性 当前对象属性
this.方法() 当前对象的方法
this(参数列表) 当前构造方法,必须放在在、第一行
【访问修饰符】
本类 | 本包其他类 | 其他包子类 | 其他包 | |
---|---|---|---|---|
public 共有的 | √ | √ | √ | √ |
protected保护的 | √ | √ | √ | |
默认的(default) | √ | √ | ||
private私有的 | √ |
重写(覆盖):子类重新写父类的方法
一大两小两相同:
两相同:方法名相同,参数列表相同
一大:访问修饰符要大于等于父类的
两小:1)返回值类型要小于等于父类, 如果是基本类型或者void,必须保持一致
2)抛出异常的类型要小于等于父类的
不能重写的方法:
构造器不能重写
私有方法不能重写
静态方法不能重写
final修饰的方法不能重写
重写的特性:
必须存在继承关系
方法名必须相同
在子类中返回值不能改变
之类的方法修饰符要大于等于父类
@Override:表示重写
重写和重载的不同点及相同点:
重载和重写 | 重写(override) | 重载(overload) |
---|---|---|
作用域 | 子重写父的 | 是同一作用域(子重载父的,重载自己) |
方法名 | 必须一致 | 必须一致 |
参数列表 | 必须一致 | 必须不一致(个数不同,类型不同) |
返回值类型 | 返回值类型要小于等于父类的,如果是基本类型或者void,必须保持一致 | 无所谓 |
访问修饰符 | 子大于等于父类 | 无所谓 |
异常 | 抛出异常的类型要小于等于父类的 | 无所谓 |
次数 | 一次 | 多次 |
多态
多态:父类的引用指向了子类的实例,同一种行为,产生的结果不同
满足多态的条件:继承,重写,向上造型
面向对象三大特征:封装,继承,多态
面向对象四大特征:封装,继承,多态,抽象
父类 变量名1 = new 子类1();
父类 变量名2 = new 子类2();
父类 类变量名3 = new 子类3();
变量名1.方法名();
变量名2.方法名();
变量名3.方法名();
同一个引用类型,使用不同的实例执行不同的操作,即父类引用指向了子类对象
多态的应用:
1、使用一个父类作为一个方法的形参,如果一个父类作为参数,可以传入父类对象,也可以传入子类对象
2、使用父类作为一个方法的返回值,(抽象类)传入的是子类对象,(接口)返回的是实现类对象
public static void main(String[] args){
父类 变量名 = new 父类();
变量名.方法名(变量名1,变量名2,...);
}
public class 父类名(){
public void 方法名(子类名1 变量名1,子类名2 变量名2,...){
变量名1.子类方法名1();
变量名2.子类方法名2();
}
}
链式调用:当方法的返回值类型是引用数据类型的时候,可以使用链式调用
父类名 变量名 = 父类变量名.方法名1().方法名2(),...;
在多态中不能直接调用子类特有的方法,只能通过强制转化实现
多态中的强制转换:
向上造型(向上转型)(自动转换):子类型赋值给父类型
父类型 变量名 = new 子类名();
向下造型(强制转换):父类型赋值给子类型(会出现类型转换异常)
子类名 变量名 = (子类名)父类变量名;
补充
instanceof:判断左边的对象是否是右边的实例,结果是boolean,是返回true,不是返回false,通常和向下造型(强制转换)结合使用
if(父类变量名 instanceof 子类名){
子类名 变量名 = (子类名)父类变量名;
}
包:主要是用来对类进行整理的,将同种类型的类放在同一个包中。com.zretc.javase.d0831
声明包语法:package 包名; 只能有一条,且必须放在有效代码第一行,注释除外
导包:当使用的类不在同一个包中时,需要导包
导包的语法:import 包名.类名; 导包可以有多条,且必须放在声明包下面,定义类上面
单类导入:import 包名.类名;
多类导入:import 包名.*;
可以直接使用的包:Java.lang
final
final:最终,不可变的,可以修饰类、变量和方法
final修饰类,不能被继承
final修饰方法,不能被重写
对于方法和类,abstract和final不能连用
常量:用final修饰常量。只有一次赋值机会,之后都不能改变,常量一般声明为static,命名规范:所有字母都大写,每个单词之间用下划线隔开(尖叫式蛇底命名法)
final修饰成员变量,在定义时必须赋值,也可以在构造器和动态块中赋值
final修饰局部变量,可以在使用前赋值
对于基本类型来说,变量中的数据不可改变
对于引用类型来说,变量中的地址值不可改变
final修饰参数,不可以赋值,值是通过方法调用传过来的,在方法内部不能改值
抽象
抽象类:类上用abstract修饰
abstract class 类名{}
抽象方法:方法上用abstract修饰,没有方法体
abstract 返回值类型 方法名();
抽象类不能实例化对象,可以使用多态方法赋值
抽象类可以有抽象方法,也可以有非抽象方法;但抽象方法中必须有抽象类
如果子类不是抽象类,则必须实现父类的抽象方法
如果子类也是抽象类,则可以不实现父类的抽象方法
抽象类中可以包含:成员变量、成员方法、常量、构造方法、静态方法、代码块、静态代码块,所以抽象类是一个用给子类服务的类,抽象方法是个子类重写的方法
static、private、final(即不能被重写的方法)不能和abstract连用
如:
public static abstract void sum();
接口
是一种公共的规范标准,引用数据类型,由常量和抽象方法组成
定义接口:
访问修饰符 interface 接口名{
常量;
抽象方法;
}
1.在默认情况下,接口中的方法都是公有抽象方法(public abstract)
public abstract 返回值类型 方法名();//abstract可以省略不写
2.接口不能实例化对象,需要通过实现类(implements)来实现
3.接口中没有构造器
4.接口中的变量,都是公有静态常量(public static final修饰)
public static final 数据类型 变量名;//static final可以省略不写
5.在Java8中,提供了接口的默认方法(default)和静态方法
default 返回值类型 方法名(){}
访问修饰符 static 返回值类型 方法名(){}
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 class | interface |
继承关系 | 单继承 | 多继承 |
构造方法 | 有 | 无 |
实例化对象 | 不能 | 不能 |
普通成员 | 可以 | 不能有变量,普通方法是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();
当外部类和内部类成员变量同名时:获取外部类成员变量的方式:外部类.this.变量名
局部内部类
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
基本类型 | 包装类型 | 父类型 |
---|---|---|
byte | Byte | Number |
short | Short | Number |
int | Integer | Number |
long | Long | Number |
float | Float | Number |
double | Double | Number |
char | Character | Object |
boolean | Boolean | Object |
装箱:基本类型转换成包装类型的过程
拆箱:包装类型转换成基本类型的过程 【手动拆装箱】 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
^:非
():分组
1、字符串查找操作:Pattern和Matcher
2、字符串匹配操作:可以通过字符串matchers方法
3、字符串替换操作:replaceAll()和replaceFirst()方法
4、字符串的分割:字符串的split()方法
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(),默认是返回类全名@哈希值
一般用作返回类中信息(成员变量的值),所以需要重写
toString方法的功能是返回字符串形式
对于print和println,如果传入了类类型变量,就是调用了toString方法
equals(),equals方法是Object中的方法,默认是判断地址相等(==)
但是建议你重写equals(),用于比较值相对
(比如String,在String类中定义了equals能够比较值相对,是因为String中重写了equals方法)
@Override
public boolean equals(Object obj) {
//当方法的形参是引用数据类型时,建议做非空处理
if(obj==null) {
return false;
}
//判断是不是同一个类型
if(obj instanceof Demo2) {
//比较具体属性,Object向下转型
Demo2 d = (Demo2) obj;
//判断name和age是否相同
if(this.name.equals(d.getName()) && d.getAge() == d.getAge()) {
return true;
}
}
return false;
}
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);
泛型
泛型:参数化的类型
泛型:泛型方法,泛型类
泛型:不支持基本类型,不能实例化对象
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);
}
泛型的好处:
1、提高程序的安全性
2、消除黄色警告
3、在编译时期将类型确定,减少了不必要的强转代码
集合
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的区别:
-
ArrayList是用数组实现的,在内存中是连续的,适合遍历和追加
-
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(异常对象){
//捕捉到异常之后执行的代码
}
check异常:
IOException(文件异常)
ParseException(编译时异常)
InterruptedException( 线程执行的时候被中断)
SQLException(数据库异常)
非check异常:
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(输出流)
| |
| |-- FileOutputStream(文件输出流)
| |-- 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进行唤醒
线程的五种状态(线程生命周期)
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(关联)
JDK 8新特性
lamada表达式
主要针对是接口,且接口中只有一个抽象方法,替换匿名内部类
无参数无返回值
public class Demo01 {
public static void main(String[] args) {
Interface1 interface1 = new Interface1() {
@Override
public void method() {
// TODO Auto-generated method stub
System.out.println("哈哈哈哈哈");
}
};
interface1.method();
// 主要针对是接口,且接口中只有一个抽象方法,替换匿名内部类的
// ①lamada表达式
Interface1 interface2 = () -> {
System.out.println("啦啦啦啦");
};
interface2.method();
// ②由于只有一条语句,所以{}可省略
Interface1 interface3 = () -> System.out.println("hello");
interface3.method();
}
}
interface Interface1 {
// 无参数无返回值
public abstract void method();
}
无参数有返回值
public class Demo02 {
public static void main(String[] args) {
// ①
Interface2 i1 = new Interface2() {
@Override
public int method() {
// TODO Auto-generated method stub
return 100;
}
};
System.out.println(i1.method());
// ②
Interface2 i2 = () -> {
return 200;
};
System.out.println(i2.method());
// ③
Interface2 i3 = () -> 300;
System.out.println(i3.method());
}
}
interface Interface2 {
// 无参数有返回值
int method();
}
有参数无返回值
public class Demo03 {
public static void main(String[] args) {
// ①
interface3 i1 = new interface3() {
@Override
public void method(int x, int y) {
// TODO Auto-generated method stub
System.out.println("x=" + x + ",y=" + y);
}
};
i1.method(1, 2);
// ②
interface3 i2 = (int x, int y) -> {
System.out.println("x=" + x + ",y=" + y);
};
i2.method(3, 4);
// ③
interface3 i3 = (int x, int y) -> System.out.println("x=" + x + ",y=" + y);
i3.method(5, 6);
// ④
interface3 i4 = (x, y) -> {
System.out.println("x=" + x + ",y=" + y);
};
i4.method(7, 8);
// ⑤
interface3 i5 = (x, y) -> System.out.println("x=" + x + ",y=" + y);
i5.method(9, 10);
}
}
interface interface3 {
// 有参数无返回值
public abstract void method(int x, int y);
}
有参数有返回值
public class Demo04 {
public static void main(String[] args) {
// ①
interface4 i1 = new interface4() {
@Override
public int method(int x, int y) {
// TODO Auto-generated method stub
return x + y;
}
};
System.out.println(i1.method(1, 2));
// ②
interface4 i2 = (int x, int y) -> {
return x + y;
};
System.out.println(i2.method(3, 4));
// ③
interface4 i3 = (int x, int y) -> x + y;
System.out.println(i3.method(5, 6));
// ④
interface4 i4 = (x, y) -> {
return x + y;
};
System.out.println(i4.method(7, 8));
// ⑤
interface4 i5 = (x, y) -> x + y;
System.out.println(i5.method(9, 10));
}
}
interface interface4 {
// 有参数有返回值
public abstract int method(int x, int y);
}
集合遍历,排序
public class Demo05 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("tom");
list.add("rose");
list.add("jack");
list.add("kimi");
list.add("july");
// 函数式接口 -- Consumer接口
list.forEach(new Consumer<String>() {
@Override
public void accept(String t) {
System.out.println(t);
}
});
System.out.println("====================================");
list.forEach((String t) -> System.out.println(t));
System.out.println("====================================");
list.forEach((t) -> System.out.println(t));
System.out.println("====================================");
list.forEach(t -> System.out.println(t));
// 比较
// Collections.sort(list,new Comparator<String>() {
//
// @Override
// public int compare(String o1, String o2) {
// // TODO Auto-generated method stub
// return o2.compareTo(o1);
// }
// });
// 升序
// Collections.sort(list, (o1, o2) -> o1.compareTo(o2));
// 降序
Collections.sort(list, (o1, o2) -> o2.compareTo(o1));
System.out.println(list);
}
}
可以调用静态方法
public class Demo06 {
public static void main(String[] args) {
Interface6 i1 = new Interface6() {
@Override
public int getInt(String s) {
// TODO Auto-generated method stub
return Integer.parseInt(s);
}
};
System.out.println(i1.getInt("123") + 1);
Interface6 i2 = (s) -> Integer.parseInt(s);
System.out.println(i2.getInt("456") + 1);
// 可以调用静态方法
Interface6 i3 = Integer::parseInt;
System.out.println(i3.getInt("789") + 1);
System.out.println("=============================");
ArrayList<String> list = new ArrayList<>();
list.add("tom");
list.add("rose");
list.add("jack");
list.add("kimi");
list.add("july");
list.forEach(System.out::println);
}
}
interface Interface6 {
int getInt(String s);
}
构造方法
public class Demo07 {
public static void main(String[] args) {
Interface7 i1 = new Interface7() {
@Override
public Person getPerson() {
return new Person();
}
};
i1.getPerson();
// 构造方法
Interface7 i2 = Person::new;
i2.getPerson();
// 有参构造方法
Interface8 interface8 = Student::new;
interface8.getStudent("tom", 18);
}
}
class Person {
public Person() {
System.out.println("创建Person对象");
}
}
interface Interface7 {
public Person getPerson();
}
class Student {
public Student(String name, int age) {
System.out.println(name + "\t" + age);
}
}
interface Interface8 {
public Student getStudent(String name, int age);
}
时间类
LocalDate
LocalDate.now():获取当前系统时间
LocalDate.of(2045, 12, 12): 指定时间
通过控制当前赋值的正负数,完成是加还是减
plusYears(-3):年份
plusMonths(-13):月份
plusDays(1):日期
plusWeeks(2):周,1代表7天
Calendar cal = Calendar.getInstance();
System.out.println(cal.getTime());
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(fmt.format(cal.getTime()));
System.out.println(cal.get(Calendar.MONTH) + 1);// 0-11
System.out.println(cal.get(Calendar.DAY_OF_WEEK) - 1);// 周日是第一天 1-7
// jdk 8之后新增时间类
LocalDate ld = LocalDate.now();// 获取当前系统时间
System.out.println(ld);
LocalDate ld2 = LocalDate.of(2045, 12, 12);// 指定时间
System.out.println(ld2);
// 通过控制当前赋值的正负数,完成是加还是减
//
ld2 = ld2.plusYears(-3);
System.out.println(ld2);
// 月份
ld2 = ld2.plusMonths(-13);
System.out.println(ld2);
// 日期
ld2 = ld2.plusDays(1);
System.out.println(ld2);
// 周 1代表7天
ld2 = ld2.plusWeeks(2);
System.out.println(ld2);
// 格式化
DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE;// 获取系统设置好的时间格式
System.out.println(dtf);
System.out.println(dtf.format(ld));
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy/MM/dd");//自定义格式
System.out.println(dtf2.format(ld));
LocalTime
// 时分秒毫秒
LocalTime lt = LocalTime.now();
System.out.println(lt);
// 格式化
DateTimeFormatter d1 = DateTimeFormatter.ofPattern("HH:mm:ss");// HH:24进制 hh:12进制
System.out.println(d1.format(lt));
LocalDateTime
// 年月日时分秒毫秒
LocalDateTime lt2 = LocalDateTime.now();
System.out.println(lt2);// 2021-10-09T14:21:27.422
DateTimeFormatter d2 = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
System.out.println(d2.format(lt2));
快捷键:
万能键: alt+/(?),main=>主方法
复制:ctrl+c
粘贴: ctrl+v
剪切: ctrl+x
撤回:ctrl+z
删除一行:ctrl+d
保存: ctrl+s
单行注释:ctrl+/(?)
多行注释:ctrl+shift+/
变成大写:ctrl+shift+x
变成小写:ctrl+shift+y
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通