javase
1.HelloWord
1.新建一个java项目
- 文件后缀名为.java
- Hello.java
- 注意点系统可能没有显示后缀名,需要手动打开
2.编写代码
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello,World!");
}
}
//Hello World!
4.编译javac.java文件,会生成一个class文件
5.运行class文件,java.class文件
注意:
- 单词的大小写要注意:java的语法规则,对大小写敏感
- 尽量使用英文命名
- 文件名和类名必须保持一致,首字母大写
- 符号不能使用中文符号
2.注释、标识符、关键字
2.1注释(注释不会被执行)
在代码量、项目结构复杂时,需要用到注释
注释是给写代码的人看的
单行注释
//Hello World
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello,World!");
}
}
快捷键:CTRL+/
多行注释
注释一段文字
/*
hhhh
hhhh
hhhhh
*/
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello,World!");
}
}
文档注释
javaDoc指令
/**
*
* @param name
* @return
* @throws Exception
*/
public String test(String name) throws Exception {
return name;
}
参数信息
@author作者名
@version版本号
@since指明最早使用的jdk版本
@param参数名
@return返回值情况
@throws异常抛出情况
2.2标识符
java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符
标识符注意点
- 所有的标识符都以字母(A-Z/a-z)、美元符$、下划线_开始
- 首字母可以是字母(A-Z/a-z)、美元符$、下划线_或数字的任何字符组合
- 不能使用关键字作为变量名或方法名
- 标识符是大小写敏感的
- 合法标识符举例:age、$salary、_value
- 非法标识符:123abc
- 可以使用中文拼音命名,但是不推荐,很low
3.数据类型
强类型语言:
要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用。
弱类型语言:
3.1基本类型
字节:
位(bit):计算机内部储存的最小单位,11001100是八位二进制数
字节(byte):是计算机中数据处理的基本单位,可以用B表示
1B(byte)=8bit(位)
1024B=1KB
1024KB=1MB
1024MB=1GB
字符:指计算机中使用的字母、数字、字和符号
转义字符(\t \n)空格 换行
基本数据类型:
整数类型:
byte
short
int
long
浮点类型:
float
特点:有限 离散 舍入误差 大约 接近但不等于
float f = 0.1f; //0.1
double d = 1.0/10; //0.1
System.out.println(f==d); //false
System.out.println(f); //0.1
System.out.println(d); //0.1
float d1 = 23232322222223222f;
float d2 = d1 + 1;
System.out.println(d1==d2); //true
double
字符类型:
char
boolean类型
默认值为false
true
false
3.2引用数据类型
类
接口
数组
4.类型转换
java是强类型语言,有些运算需要用到类型转换
(byte、short、char、int、long、float、double)
注意点
1.不能对布尔值进行转换
2.不能把对象类型转换为不相干的类型
3.把高容量转换为低容量时,强制转换
4.转换时可能存在内存溢出,或者精度问题
public class demo03 {
public static void main(String[] args) {
int i = 128;
byte b = (byte) i; //byte最大值为127,导致内存溢出
//强制转换 (类型)变量名 高-->低
//自动转换 低-->高
System.out.println(i); //128
System.out.println(b); //-128
5.变量、常量、作用域
5.1变量:可以变化的量
java是一种强类型语言、每个变量都必须声明其类型
java变量是程序中最基本的存储单元,包括(变量名、变量类型和作用域)
变量的命名规范:
- 所有变量、方法、类名:见名知意
- 类成员变量:首字母小写驼峰原则
- 局部变量:首字母小写驼峰原则
- 常量:大写字母和下划线
- 类名:首字母大写驼峰原则
- 方法名:首字母小写驼峰原则
注意:
- 每个变量都有类型,类型可以是基本类型或引用类型
- 变量名必须是合法的标识符
- 变量声明是一条完整的语句,每个声明都必须以分号结束。
5.2变量作用域
类变量 static
实例变量:从属于对象,若不自行初始化,这个类型默认值;除了基本类型其余的默认值为null
局部变量:必须声明和初始化值
public class demo04 {
static int allClicks = 0; //类变量
String str = "helloworld"; //实例变量
public void method(){
int i = 0; //局部变量
}
5.3常量(关键字final)
常量:初始化后不能再改变值,不会变动的值。
常量可以理解成一种特殊的变量,值被设定后,在程序运行中不允许被改变
常量名一般用大写字符
//final 变量名=值;
final double PI = 3.14;
final修饰符不存在先后顺序
6.运算符
- 算术运算符:+、-、*、/、%、++、--
- 赋值运算符:=
- 关系运算符:> 、<、>=、<=、==、!=
- 逻辑运算符:&&、||、!
public class demo04 {
public static void main(String[] args) {
//与(and) 或(or) 非(取反)
boolean a = true;
boolean b = false;
System.out.println("a && b:"+(a&&b)); //逻辑与运算:两个变量都为真,结果才返回为true
System.out.println("a || b:"+(a||b)); //逻辑或运算:其中一个变量为真,结果返回为true
System.out.println("!(a && b)"+!(a&&b)); //逻辑非运算:如果是真,则变为假;如果是加变为真
}
与(and) 或(or) 非(取反)
结论:
逻辑与运算:两个变量都为真,结果才返回为true
逻辑或运算:其中一个变量为真,结果返回为true
逻辑非运算:如果是真,则变为假;如果是加变为真
- 位运算符:&、|、^、~、>>、<<、>>>(了解即可)
(>>) *2
(<<) /2
底层代码,效率很高
二进制(逢二进一)
0000 0000 0
0000 0001 1
0000 0010 2
0000 0011 3
0000 0100 4
0000 1000 8
0001 0000 16
- 条件运算符:?、:(了解即可)
- 拓展赋值运算符:+=、-=、*=、/=(了解即可)
- 三元运算符
x ? y : z
//如果x为true,则结果为y,否则结果为z
7.包机制
com.xx
阿里巴巴基础手册
8.流程控制
8.1Scanner对象
java.util.Scanner是java5的新特征,实现程序和人的交互
基本语法:Scanner s = new Scanner(System.in);
通过Scanner类的next()与nextLine()方法获取输入的字符串,读取前一般要使用hasNext()与hasNextLine()判断是否还有输入的数据
next():
- 一定要读取到有效字符后才可以结束输入
- 对输入有效字符之前遇到的空白,next()方法会自动将其去掉
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
- next()不能得到带有空格的字符串
nextLine():
- 以enter为结束符,nextLine()方法返回的是输入回车之前的所有字符
- 可以获得空白
8.2顺序结构
java的基本结构是顺序结构,一般按顺序一句一句执行
顺序结构是最简单的算法结构
顺序结构是任何一个算法都离不开的一种基本算法结构
8.3选择结构
if单选择结构
public class IfDemo01 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入内容");
String s = scanner.nextLine();
if (s.equals("Hello")){
System.out.println(s);
}
System.out.println("End");
scanner.close();
}
}
if-else双选择结构
public static void main(String[] args) {
//考试分数大于60分为及格否则不及格
Scanner scanner = new Scanner(System.in);
System.out.println("请输入考试分数");
int score = scanner.nextInt();
if (score >= 60){
System.out.println("及格");
}else {
System.out.println("不及格");
}
scanner.close();
}
if多选择结构
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的考试分数");
int score = scanner.nextInt();
if (score <= 100 && score >=90){
System.out.println("成绩优秀");
}else if (score <90 && score >= 70){
System.out.println("成绩良好");
}else if (score < 70 && score >= 60){
System.out.println("成绩及格");
}else if (score < 60 && score >= 0){
System.out.println("成绩不及格");
}else {
System.out.println("输入的数字有误");
}
scanner.close();
}
switch多选择结构
判断一个变量与一系列值中某个值是否相等。每个值称为一个分支
public class SwitchDemo02 {
public static void main(String[] args) {
String name = "强哥";
switch (name){
case "强哥":
System.out.println("哇强哥来了");
break;
case "哈哈":
System.out.println("嘿嘿哈哈");
break;
default:
System.out.println("无此用户名");
}
}
}
8.4循环结构
while结构
最基本循环 while(布尔表达式){ //循环内容 }
只要布尔表达式为true,循环就会一直执行下去
大多数情况会让循环停止下来,需要一个让表达式来结束循环
public static void main(String[] args) {
int num = 0;
int sum = 0;
while (num <= 100){
sum = sum + num;
num++;
}
System.out.println(sum);
}
do……while结构
public static void main(String[] args) {
int num = 0;
int sum = 0;
do {
sum = sum +num;
num++;
}while (num <= 100);
System.out.println(sum);
}
do……while至少会执行一次
do{ //代码语句 }while(布尔表达式);
While和do……While区别
- while先判断后执行,dowhile先执行后判断
- do……while至少执行一次
for循环
for循环是支持迭代的一种通用结构,是最有效、最灵活的循环结构
语法格式:for(初始化;布尔表达式;更新){ //代码语句 }
九九乘法表
public static void main(String[] args) {
for (int y = 1; y < 10; y++) {
for (int x = 1;x <= y; x++){
System.out.print(x+"*"+y+"="+(x*y)+"\t");
}
System.out.println();
}
}
增强for循环
使用重点在数组
语法格式:for(声明语句 : 表达式){ //代码句子 }
声明语句:
声明新的局部变量,该变量的类型必须和数组元素的类型匹配。作用于限定在循环语句块,值与此时数组元素的值相等
表达式:
要访问的数组名,或者是返回值为数组的方法
8.5break continue goto
break
break在任何循环语句的主体部分,均可以break控制循环的流程,break用于强行退出循环,不执行循环剩余的语句
continue
continue语句用在循环体语句中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判断。
关于goto关键字
goto关键字很早就出现在程序设计语言中,尽管goto仍是java的一个保留字,但并未在语言中正式使用;break和continue有goto的影子
9.方法
方法是语句的集合,它们在一起执行一个功能
方法是解决一类问题的步骤的有序组合
方法包含于类或对象中
方法在程序中被创建,在其他地方被引用
设计方法的原则:
方法本意是功能块,就是实现某一个功能的语句块的集合。
设计方法时,最好保持方法的原子性(一个方法只完成一个功能,利于后期的拓展)
8.1.定义:
用来完成特定功能的代码片段
语法结构:修饰符 返回值类型 方法名(参数类型 参数名)
{方法体 return 返回值;}
方法包含一个方法头和一个方法体
修饰符:可选的,告诉编译器如何调用该方法,定义该方法的访问类型
返回值类型:方法可能会返回值。returnValueType时方法返回值的数据类型。有些方法没看有返回值,使用关键字void
方法名:方法名和参数表共同构成方法签名
参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。值被称为实参或变量。参数列表指方法的参数类型、顺序和参数的个数。参数是可选的
- 形式参数:在方法被调用时用于接受外界输入的数据
- 实参:调用方法时实际传给方法的数据
方法体:包含具体的语句、定义该方法的功能
方法调用:对象名.方法名(实参列表)
当方法返回一个值时,方法调用通常被当作一个值
public static void main(String[] args) {
int max = max(4, 3);
System.out.println(max);
}
public static int max(int a,int b){
int result = 0;
if (a == b){
System.out.println(result);
}
if (a > b){
result = a;
}else {
result = b;
}
return result;
}
方法的返回值是void,方法调用一定是一条语句
8.2.方法的重载
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
规则:
方法名称必须相同
参数列表必须不同
方法的返回类型可以相同也可以不相同
8.3可变参数
在方法声明中,在指定参数类型后加一个省略号
一个方法中只可以指定一个可变参数,必须是方法的最后一个参数,任何普通的参数必须在他之前声明。
8.4递归
递归就是:A方法调用A方法,就是自己调用自己
结构部分:
递归头:什么时候不调用自身方法(没有头进入死循环)
递归体:什么时候需要调用自身方法
小计算可以使用
9.数组
数组是相同类型数据的有序集合
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
每一个数据称作数组元素,每个数组元素通过一个下标来访问
9.1数组声明创建
先声明数组变量,才能在程序中使用数组
int[] num; //定义 首选此方法
java语言使用new操作符来创建数组
num = new int[10]; //创建一个数组,存放10个int类型的数字
数组的元素是通过索引访问,数组索引从0开始
获取数组长度
array.length()
9.2内存分析
堆:存放new的对象和数组 可以被所有的线程共享,不会存放别的对象引用
栈:存放基本变量类型(包含这个基本类型的具体数据) 引用对象的变量(会存放这个引用在堆里面的具体地址)
方法区:可以被所有的线程共享 包含所有的class和static变量
9.3三种初始化
静态初始化
//静态初始化
int[] a = {1,2,3,4,5};
System.out.println(a[0]);
//输出1
动态初始化
//动态初始化
int[] ints = new int[10];
ints[0] = 8;
System.out.println(ints[0]);
数组的默认初始化
9.4数组的基本特点
- 数组的长度是确定的。数组一旦被创建,数组的大小不可以改变
- 数组的元素必须是相同类型,不允许出现混合类型
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型
- 数组变量属于引用类型,数组可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
9.5数组边界
下标的合法区间:[0,length-1],越界就会报错
public static void main(String[] args){
int[] a = new int[2];
System.out.println(a[2]);
}
ArrayIndexOutOfBoundsException:数组下标越界异常
小结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度的确定是不可变的,不能越界
9.6多维数组
多维数组可以看成是数组的数组
二维数组就是一个特殊的一维数组
int a[][] = new int[2][5];
9.7Arrays类
数组的工具类java.utli.Arrays
由于数组对象本身没有什么方法可以调用,API中提供了一个工具类Arrays使用,可对数据对象进行一些基本操作
查看JDK帮助文档
Arrays类中的方法都是static修饰的静态方法,使用的时候可以直接使用类名调用
常用功能:
- 给数组赋值:fill方法
public static void main(String[] args) {
int[] a = {1,2,3,4,90,909,21,23};
Arrays.fill(a,0); //给数组数值进行填充
System.out.println("调用java的Arrays工具类,fill填充输出数组"+Arrays.toString(a));
}
//输出的结果:[0, 0, 0, 0, 0, 0, 0, 0]
- 对数组排序:sort方法,升序
public static void main(String[] args) {
int[] a = {1,2,3,4,90,909,21,23};
Arrays.sort(a); //数组进行排序,升序
System.out.println("调用java的Arrays工具类,sort有序输出数组"+Arrays.toString(a));
}
//输出的结果:[1, 2, 3, 4, 21, 23, 90, 909]
- 比较数组:通过equals方法比较数组中元素值是否相等
- 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作
9.8冒泡排序
两层循环,外层冒泡轮数,里层依次比较
//冒泡排序(经典中的经典)
public class ArrayDemo06 {
public static void main(String[] args) {
int[] a = {1,4,2,7,3};
int[] sort = sorts(a);
System.out.println(Arrays.toString(sort));
}
//1.比较数组中,两个相邻的元素,若第一个数比第二个数大,交换他们位置
//2.每一次比较,会产生一个最大的或最小的数字
//3.下一轮会减少一次排序
//4.依次循环
public static int[] sorts(int[] arrays){
//临时变量
int temp = 0;
//外层循环,判断要走多少次
for (int i = 0; i < arrays.length-1; i++) {
boolean flag = false; //通过flag标识符减少没有意义的比较
//内层循环,如果第一个数比第二个数大,交换位置
for (int j = 0; j < arrays.length-1-i; j++) {
if (arrays[j+1]<arrays[j]){
temp = arrays[j];
arrays[j] = arrays[j+1];
arrays[j+1] = temp;
flag = true;
}
}
if (flag == false){
break;
}
}
return arrays;
}
}
9.9稀疏数组
编写五子棋游戏,有存盘退出和续上盘的功能
介绍:
当一个数组中大部分元素为0,或为同一值的数组时,可以使用稀疏数组来保存该数组
处理方法:
- 记录数组共有几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模的数组中,缩小程序的规模(压缩)
运行
- 创建原始数组,把最初的数组输出
- 程序运行之后有两个有效值,定义array1二维数组为11行11列,第一个有效值在第二行第三列值为1,第二个有效值在第三行第四列值为2
- 转换为稀疏数组,定义循环得到array1数组的有效值并判断数组值之间相乘为不为0(数组的默认值为0),获取有效值的个数
- 创建稀疏数组,将array1非0的值保存到稀疏数组中
- 输出稀疏数组的值
//稀疏数组
public class ArrayDemo07 {
public static void main(String[] args) {
//1.创建一个二维数组11*11 0:没有棋子 1:黑棋 2:白棋
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
//输出原始数组
System.out.println("输出原始数组");
for (int[] ints : array1) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
// 转换为稀疏数组
//获取有效值的个数
int sum = 0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (array1[i][j] != 0){
sum++;
}
}
}
System.out.println("有效值的个数:"+sum);
//创建一个稀疏数组的数组
int[][] array2 = new int[sum+1][3];
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;
//遍历二维数组,将非零的值,存放到稀疏数组中
int count = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j] != 0){
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array1[i][j];
}
}
}
System.out.println("稀疏数组");
System.out.println("行"+"\t"+"列"+"\t"+"有效值");
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i][0]+"\t"+array2[i][1]+"\t"+array2[i][2]);
}
}
}
10.面向对象
10.1面向过程&面向对象
java的核心思想OOP面向对象编程
面向过程思想:
- 步骤清晰简单,第一做什么……,第二做……;
- 面对过程适合处理一些较为简单的问题
面向对象思想
- 进行分类的思维模式,思考问题首先会解决问题需要哪些分类,对这些分类进行独立思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题
10.2面向对象
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
抽象
三大特性:
- 封装
- 继承
- 多态
从代码的角度考虑是先有类后有对象。类是对象的模板
10.3回顾方法及加深
方法的定义
- 修饰符
- 返回类型
- break与return的区别
break:跳出switch,结束循环
return:结束对应的方法
- 方法名:注意规范,见名知意,驼峰法
- 参数列表:(参数类型,参数名)
- 异常抛出
方法的调用
- 静态方法
- 非静态方法
- 形参和实参
- 值传递和引用传递
- this关键字
10.4类与对象的关系
类是一种抽象的数据类型,它是对某一类事物整理描述/定义,但不能代表某一个具体的事物。
- Person类、Cat类,都是用来描述/定义某一类事物具备的特点和行为
对象是抽象概念的具体实例
- 豪二子就是人的一个具体实例,豪儿子家里dad我就是dad的一个具体实例
- 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念
创建与初始化对象
- 使用new关键字创建对象
- new创建对象时,除了分配内存空间外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
- 类中的构造器也称为构造方法,是在进行创建对象时必须调用。
public class Application {
public static void main(String[] args) {
//类:抽象的 实例化
//类实例化后会返回一个自己的对象
//student2对象就是Student2具体实例
Student2 student2 = new Student2();
student2.name = "码小贺";
student2.age = 18;
System.out.println(student2.name+"有"+student2.age+"岁");
//调用方法
student2.study();
}
}
public class Student2 {
//属性
String name;
int age;
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
构造方法:
特点:
- 和类名相同
- 没有返回值
作用:
- new本质在调用构造方法
- 初始化对象的值
注意点:
- 定义有参构造之后,如果想使用无参构造,显示的定义一个无参构造(即代码块为空)
- 无参构造是默认就有的
生成构造方法的快捷键:alt+insert
public class Pet {
public String name;
public int age;
public void shot(){
System.out.println("叫了一声");
}
}
public class Application {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name = "早早";
dog.age = 4;
dog.shot();
System.out.println(dog.name);
System.out.println(dog.age);
}
}
小结
1.类与对象:
类是一个模板,对象只是一个具体的实例
2.方法:
定义和调用
3.对应的引用:对象是通过引用来操作的:栈--->堆
4.属性:字段Field成员变量
默认初始化:
数字:0 char:u0000 boolean:false 引用类型:null
属性的定义:修饰符 属性类型 属性名 = 属性值
5.对象的创建和使用
必须使用new关键字创造对象,构造方法 Person hq = new Person();
对象的属性 hq.name
对象的方法 hq.eat()
6.类:
静态的属性 属性
动态的行为 方法
封装、继承、多态
11.封装
程序设计追求”高内聚,低耦合“
高内聚
类的内部数据操作细节自己完成,不允许外部干涉
低耦合
仅暴露少量的方法给外部使用
含义:
封装(数据的隐藏)
实际上,应禁止直接访问一个对象中数据的实际表示,而通过操作接口来访问,(即信息隐藏)
属性私有,get/set
作用
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统可维护性增加
12.继承
继承的本质是对某一批类的抽象,实现对现实世界更好的建模
extends”扩展“,子类是父类的扩展
java中类只有单继承,没有多继承
继承是类与类之间的一种关系,一个为子类,一个为父类,子类继承父类,用关键字extends来表示
Object类是所有类的父类
super关键字可以调用父类属性
调用父类的构造方法,必须要在子类构造方法的第一行
super注意点
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法
super对比this
代表的对象不同:
this:本身调用者这个对象
super:代表父类对象的应用
前提:
this:没有继承也可以使用
super:只能在继承条件才可以使用
构造方法
this():本类的构造
super():父类的构造
重写:
需要有继承类,子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大但不能缩小 public>protected>default>private
- 抛出的异常:范围,可以被缩小,但不能扩大
重写,子类的方法和父类必须一致,方法体不同!
why:父类的功能,子类不一定需要,或不一定满足
13.多态
含义:
- 即同一方法可以根据发送对象的不同而采用多种不同的行为方式
- 动态编译 类型 可拓展性
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
条件:
- 有继承关系
- 子类重写父类的方法
- 父类引用指向子类对象
注意:
-
多态是方法的多态,属性没有多态
-
父类和子类,有联系,会出现类型转换异常
-
存在条件:继承关系,方法需要重写,父类引用指向子类对象! Father f1 = new Son();
- static方法属于类,不属于实例
- final常量
- private方法
-
类型转换
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型
- 把父类转换为子类,向下转型:强制转换
- 方便方法的调用,减少重复的代码
public class Application { public static void main(String[] args) { //类型之间的转化:(与基本类型转发差不多) Person student = new Student(); //把Person类型的student转化为Student类型 //强转 //子类转化为父类,可能会丢失自己本来的方法 ((Student) student).go(); } }
public class Student extends Person{ public void go(){ System.out.println("go"); } }
public class Person { }
static关键字
静态代码块用于初始化一个类的时候做操作用的,和静态变量、静态方法一样,静态块里面的代码只执行一次,且只在初始化类的时候执行。
结论:
- 静态资源的加载顺序是严格按照静态资源的定义顺序来加载的。
- 静态代码块对于定义在它之后的静态变量,可以赋值,但是不能访问。
- 静态代码块是严格按照父类静态代码块到子类静态代码块的顺序加载的,且只加载一次。
13.抽象类
abstract修饰符用来修饰方法也可以修饰类,修饰方法时是抽象方法,修饰类时是抽象类
抽象类中可以没有抽象方法,但有抽象方法的类一定要声明为抽象类。
抽象类不能使用new关键字类创建对象,是用来让子类继承的
抽象方法,只有方法的声明,没有方法的实现,用来让子类实现。约束!
子类继承抽象类,必须要实现抽象类没有实现的抽象方法,否则该子类也要声明抽象类
抽象的意义:
- 抽象类不能使用new关键字类创建对象,是用来让子类继承;可以把一些具有相同属性和方法的组件进行抽象利于对代码和程序的维护和重用
- 又有一个类似的组件产生时,只实现该抽象类就可以获得该抽象类的属性和方法。
14.接口
只有规范!自己无法写方法 专业的约束
作用:
- 约束
- 定义一些方法,让不同的方法实现
- public abstract
- public static final
- 接口不能被实例化,接口没有构造方法
- implements可以实现多个接口
- 必须要重写接口中的方法
15.内部类
含义:
在一个类的内部在定义一个类,比如A类中定义一个B类,B类对A类来说称为内部类,A剋相对于B类来说称为外部类
1.成员内部类
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通过外部类来实例内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}
2.静态内部类
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
public static class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
}
}
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
}
}
3.局部内部类
4.匿名内部类
这些可以适当了解
16.异常
含义:程序运行中出现的不期而至的各种状况
Error类称为错误类:java程序运行时产生的系统内部错误或资源耗尽的错误,这类错误比较严重,仅靠程序本身是不能恢复运行
Exception类称为异常类,表示程序本身可以处理的错误。
异常处理关键字:try、catch、finally、throw、throws
public class Test2 {
public static void main(String[] args) {
new Test()
}
//在这个方法上抛出
public void test(int a,int b)throws ArithmeticException{
if (b == 0){
throw new ArithmeticException();//主动抛出异常,在方法中使用
}
}
}
try catch:
快捷键:CTRL+ALT+T
try { //监控区域
System.out.println(a/b);
} catch (Exception e) { //catch(想要捕获的异常类型)捕获异常
System.out.println("程序出现异常");
}finally { //处理善后工作
System.out.println("finally");
}
总结:
- 处理运行时异常,采用逻辑去合理规避同时try-catch处理
- 在多重catch块后,可以加一个catch(Exception)来处理可能会被遗漏的异常
- 对于不确定的代码,也可以加上try-catch,处理潜在的异常
- 尽量去处理异常,切记只是简单地调用printStackTrace()去打印输出
- 尽量添加finally语句块去释放占用的资源
17.javaAPI
应用程序编程接口
17.1字符串类(String)
Java中定义了3个封装字符串的类:String类、StringBuffer类、StringBuilder类。位于java.lang包
1.String类的理解和创建对象
- String对象用于保存字符串
- 字符串的字符使用Unicode字符编码
- String类有很多构造器,构造器的重建
- 常用的获取字符串方法:
- String s1 = new String();
- String s2 = new String(String original);
- String s3 = new String(Char[] a);
- String s4 = new String(Char[] a,int startIndex,int count);
- String s5 = new String(byte[] b)
- String s6 = "abc";(推荐)
- String类实现了
- 接口Serializable(String 可以串行化:可以在网络传输)
- 接口Comparable(String 可以比较大小)
- String是final(常量)类,不能被继承
- String有属性private final char value[] 用于存放字符串内容,value是一个final类型,不可以修改(地址)
创建String对象的两种方式
- 直接赋值String s = "hh";
- 调用构造器 String s = new String("hh");
String对象的特点
- 通过new创建的字符串对象,每一次new都会申请一个内存空间,虽然内容相同,但是地址值不同。
- 以""方式给出的字符串,只要字符顺序大小写相同,无论代码中出现几次JVM都只会建立一个String对象,在字符串池中维护
字符串的比较
使用==做比较
- 基本类型:比较的是数据值是否相同
- 引用类型:比较的是地址值是否相同
字符串是对象,比较内容是否相同,方法为:equals()
方法
方法名 | 作用 |
---|---|
char charAt(int index) | 返回指定位置的字符 |
int compareTo(String anotherString) | 比较两个字符串。相等返回0;前大后小返回1;前小后大返回-1 |
boolean contains(CharSequence s) | 判断字符串是否包含s |
boolean endsWith(String suffix) | 判断字符串是否以suffix结尾 |
boolean equals(Object anObject) | 判断两个串是否相等 |
boolean equalsIgnoreCase(String anotherString) | 忽略大小写判断两个串是否相等 |
byte[] getBytes() | 将字符串串变成字节数组返回 |
int indexOf(String str) | 返回str在字符串第一次出现的位置 |
boolean isEmpty() | 字符串是否为空 |
int length() | 字符串长度 |
int lastIndexOf(String str) | 返回str最后一次出现的位置 |
String replace(CharSequence target, CharSequence replacement) | 用replacement替换字符串target的字符 |
String[] split(String regex) | 将字符串以regex分割 |
boolean startsWith(String prefix) | 判断字符串是否以prefix开始 |
String substring(int beginIndex) | 从beginIndex开始截取字串 |
String substring(int beginIndex, int endIndex) | 截取beginIndex到endIndex - 1的字符串 |
char[] toCharArray() | 将字符串转换乘char数组 |
String toLowerCase() | 字符串转小写 |
String toUpperCase() | 字符串转大写 |
String trim() | 去除字符串两边空格 |
静态方法 | |
static String valueOf(int i) | 将 i 转换成字符串 |
StringBuffer类
在 Java中,除了通过 String 类创建和处理字符串之外,还可以使用 StringBuffer 类来处理字符串。StringBuffer 类可以比 String 类更高效地处理字符串。
创建StringBuffer类
StringBuffer 类提供了 3 个构造方法来创建一个字符串
- StringBuffer() 构造一个空的字符串缓冲区,并且初始化为 16 个字符的容量。
- StringBuffer(int length) 创建一个空的字符串缓冲区,并且初始化为指定长度 length 的容量。
- StringBuffer(String str) 创建一个字符串缓冲区,并将其内容初始化为指定的字符串内容 str,字符串缓冲区的初始容量为 16 加上字符串 str 的长度。
StringBuffer str1 = new StringBuffer();
StringBuffer str2 = new StringBuffer(10);
// 定义一个含有(16+4)的字符串缓冲区,"青春无悔"为4个字符
StringBuffer str3 = new StringBuffer("码小贺");
/*
*输出字符串的容量大小
*capacity()方法返回字符串的容量大小
*/
System.out.println(str1.capacity()); // 输出 16
System.out.println(str2.capacity()); // 输出 10
System.out.println(str3.capacity()); // 输出 19
StringBuffer方法
追加字符串
StringBuffer 类的 append() 方法用于向原有 StringBuffer 对象中追加字符串。
语法格式:StringBuffer 对象.append(String str)
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer("学生成绩管理");
System.out.println("欢迎进入《"+stringBuffer+"》系统");
// 声明课程名称字符串
StringBuffer courseName = new StringBuffer();
System.out.println("请输入本期学生的成绩");
Scanner scanner = new Scanner(System.in);
// 循环接收控制台输入的字符串
for (int i = 0; i < 5; i++) {
String grade = scanner.next();
courseName.append(grade+"\t");
if (i==4){
System.out.println("录入完毕");
}
}
System.out.println("本学期的学生成绩如下:\n"+courseName);
}
反转字符串
StringBuffer 类中的 reverse() 方法用于将字符串序列用其反转的形式取代。
语法格式:StringBuffer 对象.reverse();
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer("贺小码");
stringBuffer.reverse();
System.out.println(stringBuffer);
}
替换字符串
该方法的作用是修改对象中索引值为 index(下标) 位置的字符为新的字符
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("hello");
sb.setCharAt(0,'H');
System.out.println(sb);
sb.setCharAt(1,'E');
System.out.println(sb);
sb.setCharAt(2,'L');
System.out.println(sb);
sb.setCharAt(3,'L');
System.out.println(sb);
sb.setCharAt(4,'O');
System.out.println(sb);
}
删除字符串
StringBuffer 类提供了 deleteCharAt() 和 delete() 两个删除字符串的方法
1.deleteCharAt()方法
deleteCharAt() 方法用于移除序列中指定位置的字符
语法格式:StringBuffer 对象.deleteCharAt(int index);
deleteCharAt() 方法的作用是删除指定位置的字符,然后将剩余的内容形成一个新的字符串。
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer("woman");
stringBuffer.deleteCharAt(0);
System.out.println(stringBuffer);
stringBuffer.deleteCharAt(0);
System.out.println(stringBuffer);
}
注意:在使用deleteCharAt方法时,woman该字符串第一次使用此方法w位置下标为0;在进行第二次使用时,o的下标为零。
2.delete()方法
delete() 方法用于移除序列中子字符串的字符
语法格式:StringBuffer 对象.delete(int start,int end);
start 表示要删除字符的起始索引值(包括索引值所对应的字符),end 表示要删除字符串的结束索引值(不包括索引值所对应的字符)。该方法的作用是删除指定区域以内的所有字符
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer("woman");
stringBuffer.delete(0,2);
System.out.println(stringBuffer);
}
StringBuilder
public final class StringBuilder
extends Object
implements Serializable, Comparable<StringBuilder>, CharSequence
StringBuilder的相关信息
一个可变的字符序列, 此类提供与StringBuffer
兼容的API,但不保证同步。
此类设计用作StringBuffer
替代品,用于单个线程使用字符串缓冲区的位置(通常情况下)。 在可能的情况下,建议使用此类优先于SringBuffer因为在大多数实现中它会更快。
它们被重载以便接受任何类型的数据。 每个都有效地将给定的数据转换为字符串,然后将该字符串的字符追加或插入到字符串构建器中。
1.append()方法:终在构建器的末尾添加这些字符
2.insert()方法:指定点添加字符
StringBuilder
实例不适合多线程使用。 如果需要这样的同步,则建议使用StringBuffer
。
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("欢迎来到");
System.out.println(stringBuilder.append("我的世界"));
System.out.println("删除插入后:"+stringBuilder.delete(0,4).insert(0,"哈哈!").replace(2,3,","));
System.out.println("替换后:"+stringBuilder.replace(0,3,"欢迎来到"));
}
17.2System类
定义了一些与系统相关的属性和方法,提及的属性和方法都是静态的
1.arraycopy()方法
用于将数组从原数组复制到目标数组
语法格式:
static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
src:表示源数组
dest:表示目标数组
srcPos:表示源数组中复制元素的起始位置
destPos:表示复制到目标数组的起始位置
length:表示复制元素的个数
注意:
在进行数组复制,目标数组必须有足够的空间来存放复制的元素,否则会发生角标越界异常。
public static void main(String[] args) {
int[] fromArray = {10,11,12,13,14,15}; //源数组
int[] toArray = {20,21,22,23,24,25,26}; //目标数组
System.arraycopy(fromArray,2,toArray,3,4); //复制数组元素
//打印复制后的数组
for (int i = 0; i < toArray.length; i++) {
System.out.println(i+":"+toArray[i]);
}
}
2.currentTimeMillis()方法
该方法用于获取当前系统的时间。返回值为long类型,单位为毫秒,该值也称为时间戳
public static void main(String[] args) {
long startTime = System.currentTimeMillis(); //循环开始的时间
int sum = 0;
for (int i = 0; i < 1000000000; i++) {
sum += i;
}
long endTime = System.currentTimeMillis(); //循环结束的当前时间
System.out.println("程序运行的时间为:"+(endTime - startTime)+"毫秒");
}
3.getProperties()和getProperty()方法
getProperties()方法:用于获取当前系统的全部属性,该方法会返回一个Properties对象,其中封装了所有的属性,这些属性都是以键值对存在。
getProperty()方法:用于根据系统的属性名获取对应的属性值
4.gc()方法
当一个对象成为垃圾后会占用内存空间,java引入了垃圾回收机制,java虚拟机会自动回收垃圾对象所占用的内存空间。
class Person{
//定义方法,在垃圾回收前被调用
public void finalize(){
System.out.println("对象将被作为垃圾回收");
}
}
public class System04 {
public static void main(String[] args) {
//创建两个Person对象
Person p1 = new Person();
Person p2 = new Person();
//下面将变量置为null,让对象成为垃圾
p1 = null;
p2 = null;
//回收
System.gc();
for (int i = 0; i < 1000000; i++) {
//为了延长程序运行的时间
}
}
}
exit方法,用于终止当前正在运行的java虚拟机
exit(int status) status表示当前发生的异常状态,通常指定为0,表示正常退出,否则表示异常终止。
17.3.Runtime类
用于查看和控制虚拟机的状态和行为,用于封装java虚拟机进程。每次使用Java命令启动虚拟机都对应一个Runtime实例,在定义Runtime类时,它的构造方法被私有化,对象不可以直接实例化。
1.获得一个Runtime实例(对象):
Runtime run = Runtime.getRuntime();
2.常用方法:
- (1) freeMemory():该方法用于返回Java虚拟机中的空闲内存量,以字节为单位。
-
(2) maxMemory():该方法用于返回Java虚拟机试图使用的最大内存量。
-
(3) totalMemory():该方法用于返回Java虚拟机中的内存总量。
-
(4)availableProcessors():返回虚拟机的处理器数量
-
(5)exit(int status): 通过启动其关闭序列来终止当前正在运行的Java虚拟机
-
(6)getRuntime():该方法用于返回当前应用程序的运行环境对象
-
(7)exec(String command)根据指定的路径执行对应的可执行文件
1.获取当前虚拟机信息:
exec()方法相当于执行一个DOS命令
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime(); //获得一个Runtime实例
System.out.println("处理器的个数:"+runtime.availableProcessors()+"个");
System.out.println("空闲内存数量:"+runtime.freeMemory()/1024/1024+"M");
System.out.println("最大内存可用数量:"+runtime.maxMemory()/1024/1024+"M");
System.out.println("虚拟机中内存总量:"+runtime.totalMemory()/1024/1024+"M");
}
内存的单位为byte(1KB=1024B 1MB=1024KB)
2.操作系统进程:
public static void main(String[] args) throws IOException {
Runtime runtime = Runtime.getRuntime(); //创建Runtime对象
runtime.exec("msedge.exe"); //调用exec()方法
}
}
17.4Math类
public static void main(String[] args) {
System.out.println("计算绝对值的结果:"+Math.abs(-8));
System.out.println("求大于参数的最小整数:"+Math.ceil(7.6));
System.out.println("求小于参数的最大整数"+Math.floor(8.8));
System.out.println("对小数进行四舍五入后的结果:"+Math.round(8.3));
System.out.println("求两个数的较大值:"+Math.max(7,8));
System.out.println("求两个数的较小值:"+Math.min(8,9));
System.out.println("生成一个大于等于0.0小于1.0的随机数:"+Math.random());
System.out.println("开平方的结果:"+Math.sqrt(64));
System.out.println("指数函数的值:"+Math.pow(2,3));
}
Math.random()只能找大于等于0.0小于1.0的随机数
17.5Random类
该类,可以在指定的取值范围随机产生数字。
Random提供了两个构造方法
1.Random(),用于创建一个伪随机生成数(无参)
public static void main(String[] args) {
Random r1 = new Random();
//随机产生10个(0-100)的整数
for (int i = 0; i < 10; i++) {
System.out.println(r1.nextInt(100));
}
}
第一次产生随机数
第二次产生随机数
2.Random(long seed),使用一个long类型的seed(种子)创建伪随机数生成器
public static void main(String[] args) {
Random r1 = new Random(88); //创建对象时传入指定参数(种子),所产生的随机数序列也不会变
//随机生成10个0-100的整数
for (int i = 0; i < 10; i++) {
System.out.println(r1.nextInt(100));
}
}
创建对象时传入指定参数(种子),所产生的随机数序列也不会变
17.6日期时间类
位于java.time包
Instant类
该类是java8补充的一个时间戳类
相比于System.currentTimeMillis()获取到毫秒,Instant可以获取到纳秒。
Instant可以使用静态方法 now() 或者 of() 方法来创建一个实例对象。
Instant 类的常用API 就是获取时间戳了
- Instant 类的 getEpochSecond() : 获取的是秒
- Instant 类的 toEpochMilli() : 获取的是毫秒,同 System.currentTimeMillis()
- Instant 类的 getNano() : 获取的是纳秒,更精确了
- Instant 类还是 Java8 中 提供的新的 日期时间类LocalDateTime 与 原来的 java.util.Date 类之间转换的桥梁。
声明方法:
- now() 从系统时钟获取当前时刻
- now(Clock clock) 从系统时钟获取当前时刻
- ofEpochSecond(long epochSecond) 从自标准java计算时代开始的秒数获得的一个Instant实例
- ofEpochMilli(long epochMilli) 从自标准java计算时代开始的毫秒数获得的一个Instant实例
- getEpochSecond()从1970-01-01T00:00:00的标准java计算时代获取秒数
- getNano()从第二秒开时表示的时间线中返回纳秒数
- parse(CharSequence text)从一个文本字符串获取一个Instant实例
- from(TemporalAccessor tenporal)从时间对象获取一个Instant实例
public static void main(String[] args) {
// 初始化 1970-01-01 00:00:00开始
Instant now = Instant.now();
System.out.println("从系统或取得当前时刻为:"+now);
Instant instant01 = Instant.ofEpochMilli(1000 * 60 * 60 * 24);
System.out.println("计算机元年增加毫秒数后为:"+instant01);
Instant instant02 = Instant.ofEpochSecond(60 * 60 * 24);
System.out.println("计算机元年增加秒数后为:"+instant02);
System.out.println("获取的秒值为:"+Instant.parse("2020-11-05T12:28:34.864Z").getEpochSecond());
System.out.println("获取的纳秒值为:"+Instant.parse("2020-11-05T12:28:34.864Z").getNano());
System.out.println("从时间对象获取的Instant实例为:"+Instant.from(now));
}
LocalDate类
该类用来表示日期。通常表示的是年份和月份,但是不能代表时间线上的即时信息,只是日期的描述。
LocalDate类的常用函数
LocalTime now()
构造一个表示当前日期的对象。即:构造一个 YYYY MM DD格式的实例
LocalTime of(int year, int month, int day)
构造一个表示给定日期的对象。即:给一个日期2019-1-08,就会构造一个这个日期的Date类实例
DayOfWeek getDayOfWeek
得到当前日期是星期几,作为DayOfWeek类的一个实例返回,调用getValue来得到1~7之间的一个数,表示这是星期几,1表示星期一,7表示星期日。例子:DayOfWeek weekday = date.getDayOfWeek(); int value = weekday.getValue();得到当前日期是星期几。
LocalDate plusDays(int n)
增加日期
LocalDate minusDays(int n)
减少日期
public static void main(String[] args) throws UnsupportedTemporalTypeException {
//获取时间和日期
LocalDate now = LocalDate.now();
LocalDate of = LocalDate.of(2020, 11, 5);
System.out.println("1LocalDate获取格式化的相关方法");
System.out.println("从LocalDate实例获取的年份为:"+now.getYear());
System.out.println("从LocalDate实例获取的月份:"+now.getMonthValue());
System.out.println("从LocalDate实例获取当天在本月的第几天:"+now.getDayOfMonth());
// System.out.println("从获取到的LocalDate实例格式化为:"+now.format (DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss")));
//使用LocalDateTime
LocalDateTime now1 = LocalDateTime.now();
String year = now1.format(DateTimeFormatter.ofPattern("yyyy"));
String hour = now1.format(DateTimeFormatter.ofPattern("MM-dd-HH"));
System.out.println(year+"-"+hour);
System.out.println("2LocalDate判断的相关方法");
System.out.println("判断日期of是否在now之前:"+of.isBefore(now));
System.out.println("判断日期of是否在now之后:"+of.isAfter(now));
System.out.println("判断日期of和now是否相等:"+now.equals(of));
System.out.println("判断日期of是否为闰年:"+of.isLeapYear());
System.out.println("3LocalDate解析以及加减操作的相关方法");
String dateStr = "2020-02-01";
System.out.println("把日期字符串解析为日期对象为"+LocalDate.parse(dateStr));
System.out.println("将LocalDate实例年份加1为:"+now.plusYears(1));
System.out.println("将LocalDate实例天数减10为:"+now.minusDays(10));
System.out.println("将LocalDate实例指定年份为:2014"+now.withYear(2014));
}
LocalTime类
该类表示的是时间,通常是小时、分钟、秒,不能代表时间线上的即时信息,只是事件的描述。与LocalDate类相似
-
1.创建时间类对象
-
1.1 获取当前时间
-
LocalTime.now() : 获取默认时区下的系统时钟的时间
-
LocalTime.now(Clock clock) : 获取指定时钟的时间
-
LocalTime.now(ZoneId zone) : 获取指定时区的、默认系统时钟的时间
-
【补充:获取所有时区信息的方式 : ZoneId.getAvailableZoneIds()】
-
1.2 获取指定时间
-
- 小时的取值范围 : [0,23]
-
- 分钟的取值范围 : [0,59]
-
- 秒 的取值范围 : [0,59]
-
- 纳秒的取值范围 : [0,999,999,999]
-
LocalTime.of(int hour, int minute) : 指定小时和分钟,秒和纳秒为0
-
LocalTime.of(int hour, int minute, int second) : 指定小时、分钟、秒,纳秒为0
-
LocalTime.of(int hour, int minute, int second, int nanoOfSecond) : 指定小时、分钟、秒、纳秒
-
LocalTime.ofSecondOfDay(long secondOfDay) : 指定一天当中的多少秒,纳秒将被置为0
-
LocalTime.ofNanoOfDay(long nanoOfDay) : 指定一天当中的多少纳秒
LocalDateTime类
LocalDateTime是LocalDate和LocalTime的结合
LocalDateTime默认格式为:2022-11-05T21:30:00.774,经常与DateTimeFormatter一起使用
Period类
该类用于计算两个日期的间隔,与Duration类似,也是通过between计算日期间隔
getYears() 获取年份
getMonths() 获取月份
getDays() 获取天数
public static void main(String[] args) {
LocalDate date = LocalDate.of(2022, 11, 05);
LocalDate now = LocalDate.now();
//计算两个日期的间隔
Period between = Period.between(date, now);
System.out.println("时间间隔为:"+between.getYears()+"年");
System.out.println("时间间隔为:"+between.getMonths()+"月");
System.out.println("时间间隔为:"+between.getDays()+"天");
}
Duration类
该类基于时间值,其作用范围是:天、时、分、秒、毫秒和纳秒
Duration的常用方法
between() 获取一个Duration表示两个事件对象之间的持续时间
toDays() 将时间转换为天为单位
toHours() 将时间转换为小时为单位
toMinutes() 将时间转换为分钟为单位
toMillis() 将时间转换为毫秒为单位
toNaons() 将时间转换为纳秒为单位
public static void main(String[] args) {
LocalTime start = LocalTime.now();
LocalTime end = LocalTime.of(20, 12, 23);
Duration between = Duration.between(start, end);
//间隔的时间
System.out.println("时间的间隔为:"+between.toHours()+"小时");
System.out.println("时间的间隔为:"+between.toMillis()+"毫秒");
System.out.println("时间的间隔为:"+between.toNanos()+"纳秒");
}
17.7包装类
java是一种面向对象的语言,“万物皆对象”,java中的类可以把方法和数据连接在一起,但是java中不能把基本的数据类型当作对象来处理,可以把基本数据类型的值包装为引用数据类型的对象。
包装类和基本数据类型的转换
为了使用方便Java中将8种基本数据类型进行了封装:除了Integer和Character类以外,其它六个类的类名和基本数据类型一直,只是类名的第一个字母大写即可。
boolean —> Boolean char —> Character byte—> Byte short—> Short long—> Long int —> Integer float—> Float double—>Double
int和Integer类之间的转换
使用Integer类的构造方法和Integer类内部的intValue方法实现这些类型之间的相互转换
public static void main(String[] args) {
int n = 5;
Integer integer = new Integer(n);
System.out.println("int类型转换为Integer类型:"+integer);
Integer integer1 = new Integer(88);
int b1 = integer1.intValue();
System.out.println("Integer类转换为int类:"+b1);
}
自动拆装箱
在进行基本数据类型和对应的包装类转换时,系统将自动进行.
自动装箱:将 基本数据类型 封装为对象类型,来符合java的面向对象的思想。
自动拆箱:将对象重新转化为基本数据类型。
public static void main(String[] args) {
//5是基本数据类型,通过自动装箱变成对象类型。
Integer i=5;
//编译器执行了Integer i = Integer.valueOf(5)
int i2=i;
//自动拆箱,实际上执行了 int i2 = i.intValue()
System.out.println(i2);
}
value0f()源码分析:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
其中low的值为-128,high为127
包装类的缓存值:
boolean:true和false
byte:-128~127
char:0~127
short:-128~127
int:-128~127
long:-128~127
特别注意:对于float和double没有缓存。
注意点:在对上述值进行装箱的时候,并不是创建一个新对象而是使用缓存中的对象,如果超出范围才需要新建立对象。
包装类的好处
- 首先包装类是一种类,类就有定义好的属性或方法,这些方法对应就完成了一些特定的功能,我们可以调用这些方法完成一些工作,简化了我们自己的编码量,没有这些方法,我们需要这些功能时就要自己编程去实现。
- 基本数据类型都用隐式的默认值,不是类的对象,不能为null,很多时候我们可能需要我们的这些类型可以为null,这时就需要用包装类了
17.8正则表达式(regular expression)
1.体验正则表达式
1.获取文本英文单词
public static void main(String[] args) {
String content = "1995年,互联网的蓬勃发展给了Oak机会。业界为了使死板、单调的静态网页能够“灵活”起来," +
"急需一种软件技术来开发一种程序,这种程序可以通过网络传播并且能够跨平台运行。" +
"于是,世界各大IT企业为此纷纷投入了大量的人力、物力和财力。这个时候,Sun公司想起了那个被搁置起来很久的Oak,并且重新审视了那个用软件编写的试验平台," +
"由于它是按照嵌入式系统硬件平台体系结构进行编写的,所以非常小,特别适用于网络上的传输系统," +
"而Oak也是一种精简的语言,程序非常小,适合在网络上传输。Sun公司首先推出了可以嵌入网页并且可以随同网页在网络上传输的Applet" +
"(Applet是一种将小程序嵌入到网页中进行执行的技术),并将Oak更名为Java。5月23日,Sun公司在Sun world会议上正式发布Java和HotJava浏览器。" +
"IBM、Apple、DEC、Adobe、HP、Oracle、Netscape和微软等各大公司都纷纷停止了自己的相关开发项目,竞相购买了Java使用许可证," +
"并为自己的产品开发了相应的Java平台。";
//提取文章的所有英文单词
//(1).传统方式:代码量大,效率不高
//(2).体验正则表达式
//1.创建一个Pattern对象,可以理解为一个正则表达式对象
Pattern pattern = Pattern.compile("[a-zA-Z]+");
//2.创建一个匹配器对象
//理解:matcher匹配器按照pattern(模式/样式),到content文本中去匹配
//找到返回true,否则返回false
Matcher matcher = pattern.matcher(content);
//3.开始循环匹配
while (matcher.find()){
//匹配内容放到m.group(0)
System.out.println("找到:"+matcher.group(0));
}
}
2.获取文本中所有的数字
public static void main(String[] args) {
String content = "1995年,互联网的蓬勃发展给了Oak机会。业界为了使死板、单调的静态网页能够“灵活”起来," +
"急需一种软件技术来开发一种程序,这种程序可以通过网络传播并且能够跨平台运行。" +
"于是,世界各大IT企业为此纷纷投入了大量的人力、物力和财力。这个时候,Sun公司想起了那个被搁置起来很久的Oak,并且重新审视了那个用软件编写的试验平台," +
"由于它是按照嵌入式系统硬件平台体系结构进行编写的,所以非常小,特别适用于网络上的传输系统," +
"而Oak也是一种精简的语言,程序非常小,适合在网络上传输。Sun公司首先推出了可以嵌入网页并且可以随同网页在网络上传输的Applet" +
"(Applet是一种将小程序嵌入到网页中进行执行的技术),并将Oak更名为Java。5月23日,Sun公司在Sun world会议上正式发布Java和HotJava浏览器。" +
"IBM、Apple、DEC、Adobe、HP、Oracle、Netscape和微软等各大公司都纷纷停止了自己的相关开发项目,竞相购买了Java使用许可证," +
"并为自己的产品开发了相应的Java平台。";
//提取文章中所有的数字
//1.创建一个Pattern对象,可以理解为一个正则表达式对象
Pattern pattern = Pattern.compile("[0-9]+");
//2.创建一个匹配器对象
//理解:matcher匹配器按照pattern(模式/样式),到content文本中去匹配
//找到返回true,否则返回false
Matcher matcher = pattern.matcher(content);
//3.开始循环匹配
while (matcher.find()){
//匹配内容放到m.group(0)
System.out.println("找到:"+matcher.group(0));
}
}
3.获取IP地址
public static void main(String[] args) {
String content = "私有地址(Private address)属于非注册地址,专门为组织机构内部使用。\n" +
"以下列出留用的内部私有地址\n" +
"A类 10.0.0.0--10.255.255.255\n" +
"B类 172.16.0.0--172.31.255.255\n" +
"C类 192.168.0.0--192.168.255.255";
//1.创建一个Pattern对象,可以理解为一个正则表达式对象
Pattern pattern = Pattern.compile("\\d+\\.\\d+\\.\\d+\\.\\d+");
//2.创建一个匹配器对象
//理解:matcher匹配器按照pattern(模式/样式),到content文本中去匹配
//找到返回true,否则返回false
Matcher matcher = pattern.matcher(content);
//3.开始循环匹配
while (matcher.find()){
//匹配内容放到m.group(0)
System.out.println("找到:"+matcher.group(0));
}
}
2.正则表达式用途
正则表达式专门处理类似文本处理问题,即对字符串执行模式匹配的技术。
分析java的正则表达式的底层实现
public static void main(String[] args) {
String content = "1998年12月8日,第二代Java平台的企业版J2EE发布。1999年6月,Sun公司发布了第二代Java平台(" +
"简称为Java2)的3个版本:J2ME(Java2 Micro Edition,Java2平台的微型版),应用于移动、无线及有限资源的环境;" +
"J2SE(Java 2 Standard Edition,Java 2平台的标准版),应用于桌面环境;J2EE" +
"(Java 2Enterprise Edition,Java 2平台的企业版),应用于基于Java的应用服务器。Java 2平台的发布," +
"是Java发展过程中最重要的一个里程碑,标志着Java的应用开始普及9889";
//匹配所有四个数字
//说明:
//1.\\d:一个0-9的任意的数字
String regStr ="(\\d\\d)(\\d\\d)";
//2.创建模式对象[正则表达式对象]
Pattern pattern = Pattern.compile(regStr);
//3.创建匹配器
//创建匹配器matcher,按照正则表达式规则去匹配content字符串
Matcher matcher = pattern.matcher(content);
//4.开始匹配
while (matcher.find()){
System.out.println("找到:"+matcher.group(0));
System.out.println("第1组()匹配到的值="+matcher.group(1));
System.out.println("第2组()匹配到的值="+matcher.group(2));
}
}
//源码:
public String group(int group) {
if (first < 0)
throw new IllegalStateException("No match found");
if (group < 0 || group > groupCount())
throw new IndexOutOfBoundsException("No group " + group);
if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
return null;
return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
}
matcher.find()实现的任务(考虑分组)
分组:(\d\d)(\d\d),正则表达式中()表示分组
1.根据制定的规则,定位满足子字符串(如(19)(98))
2.找到后将子字符串的开始的索引记录到matcher对象的属性int[] groups;
2.1 groups[0] = 0,把该子字符串结束的索引+1的值记录到groups[1]=4
2.2 记录1组()匹配到的子字符串groups[2] = 0 groups[3] = 索引+1 1+1=2
2.3 记录2组()匹配到的子字符串groups[4] = 2 groups[5] = 索引+1 2+1=3
3.同时记录到的oldlast的值为 子字符串结束的索引+1的值 4 ,下次执行find方法时,就从4开始匹配 matcher.group(0)
1.根据groups[0] = 0和 groups[1] = 4的记录的位置,从conmtent开始截取的字符串返回:[0,4]包含0但是不包含索引为4的位置
0和4表示的是字符char的位置
3.正则表达式语法
1.元字符功能:
- 限定符
- 选择匹配符
- 分组组合和反向引用符
- 特殊字符
- 字符匹配符
- 定位符
- 元字符转义号
在使用正则表达式去检索某些特殊字符,需要用到转义符号,否则检索不到结果会报错。
public static void main(String[] args) {
String content = "abc$(abc(123(";
//匹配(
String regStr = "\\(";
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()){
System.out.println("找到"+matcher.group(0));
}
}
- 元字符-字符匹配符
正则表达式实现不区分大小写
- (?i)abc 表示abc都不区分大小写
- a(?i)bc 表示bc不区分大小写
- a((?i)b)c 表示只有b不区分大小写
- 当创建Pattern对象时,指定Pattern.CASE_INSENSITIVE,表示匹配不区分大小写
Pattern pattern = Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
- 【^a-z】表示可以匹配不是a-z中的任意一个字符
17.9Pattern类和Matcher类
Pattern类可以创建一个正则表达式,语法格式:
Pattern p = Pattern.compliea9("\w+");
常用方法:
split(CharSequence input) 将给定的输出序列分成这个模式的匹配
Matcher matcher(CharSequence input) 提供了对正则表达式的分组支持,以及对正则表达式的多次匹配支持
Static boolean matches(String regex,CharSequence input) 编译给定的正则表达式,并尝试匹配给定输入
public static void main(String[] args) {
Pattern p = Pattern.compile("\\d+");
String[] str = p.split("我的QQ是:21212121我的电话是:0532214我的邮箱是aaa@aaa.com");
System.out.println("是否匹配Pattern的输入模式"+Pattern.matches("\\d+","2223"));
System.out.println("是否匹配Pattern的输入模式"+Pattern.matches("\\d+","2223aa"));
Matcher m = p.matcher("22bb23");
System.out.println("返回该Matcher对象是由哪个Pattern对象创建的,即p为:"+m.pattern());
System.out.print("将给定的字符串分割成Pattern模式匹配为:");
for (int i = 0; i < str.length; i++) {
System.out.print(str[i]+" ");
}
}
2.Matcher类
该类用于在给定Pattern实例的模式控制下进行字符串的匹配工作,Matcher的构造方法也是私有的,不能直接创建。
常用方法
boolean matches() 对整个字符串进行匹配,只有整个字符串都匹配才能返回true
boolean lookingAt() 对前面的字符串进行匹配,只有匹配到的字符串在最前面才返回true
boolean find() 对字符串进相匹配,匹配到的字符串可以在任意位置
int end() 返回最后一个字符匹配后偏移量
string gropu() 返回匹配到的子字符串
int start() 返回匹配到的子字符串在字符串中的索引位置
public static void main(String[] args) {
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("22bb23");
System.out.println("字符串是否匹配"+m.matches());
Matcher m2 = p.matcher("2223");
System.out.println("字符串是否匹配"+m2.matches());
System.out.println("对前面的字符串匹配结果为"+m.lookingAt());
Matcher m3 = p.matcher("aa2223");
System.out.println("对前面的字符串匹配结果为:"+m3.lookingAt());
m.find(); //返回true
System.out.println("字符串任何位置是否匹配"+m.find());
m3.find(); //返回true
System.out.println("字符串任何位置是否匹配"+m3.find());
Matcher m4 = p.matcher("aabb");
System.out.println("字符串任何位置是否匹配"+m4.find());
Matcher m1 = p.matcher("aaa2223bb");
m1.find(); //匹配2223
System.out.println("上一个匹配的起始索引:"+m1.start());
System.out.println("最后一个字符匹配后的偏移量:"+m1.end());
System.out.println("匹配到的子字符串:"+m1.group());
}
文章内容来源:
bilibili:狂神说java基础
bilibili:韩顺平讲java
菜鸟教程:https://www.runoob.com/