由于图片上传问题,我将文件转化为PDF,这样既可以查看文章图片,也可以下载保存
https://download.csdn.net/download/peterbearXY/15289857

文章目录

  • 引言
  • 什么是JAVA
  • 第一个JAVA程序
    • 结果
  • JAVA的数据类型
      • 内置数据类型
      • 引用数据类型
    • 内置数据类型
      • 整型
      • 浮点型
      • 字符型
      • 布尔型
    • 引用数据类型
    • 基础类型转换
      • 自动类型转换
      • 强制类型转换
  • JAVA符号
    • 算数运算符
    • 关系运算符
    • 逻辑运算符
    • 补充
  • JAVA逻辑判断
    • if / else
    • switch case
  • JAVA循环
    • for循环
    • while循环
      • break
      • continue
    • do while循环
  • 判断与循环的应用
    • 求最大公因数
    • 求100以内的素数
    • 不死神兔
    • 水仙花数
    • 99乘法表
    • 求Pi的值
  • JAVA函数
    • 格式
    • 作用域
    • void关键字
    • 函数调用其他函数
  • JAVA数组
    • 创建数组
    • 访问数组元素
    • 遍历数组
    • 数组与函数
      • 将数组作为参数传入函数
      • 将数组作为返回值输出
    • 多维数组
      • 小案例 Tic-Tac-Toe (井字棋)
      • 案例2,打印二维数组初始值
  • JAVA类与对象
    • 对象创建
      • 构造方法
        • 无参构造
        • 有参构造
      • 注意
    • 对象方法
      • this关键字
      • 方法重载Overload
    • 对象封装
    • 对象继承
      • 介绍
      • 多态
        • 向上转型
        • 向下转型
        • instanceof关键字
      • super关键字
    • 对象是引用类型
    • 包装类
  • JAVA字符串
    • 常用方法
  • JAVA修饰符
    • static
      • 静态方法
      • 静态代码块
      • 静态类
    • final
      • 最终类
      • 最终变量
      • 最终方法
      • 对象常量
    • abstract
      • 抽象类
      • 抽象方法
  • JAVA接口
    • 介绍
    • interface关键字
    • 注意
    • 补充
    • 案例
  • JAVA内部类
    • 成员内部类
    • 静态内部类
    • 局部内部类
    • 匿名内部类
  • JAVA泛型
    • 泛型方法
    • 泛型类
    • 泛型接口
    • 通配符
  • JAVA集合
    • Collection接口
      • List接口
        • ArrayList
        • LinkedList
      • Set接口
        • HashSet
        • TreeSet
    • Map接口
      • Map遍历
      • HashMap
      • TreeMap
  • JAVA常用类
    • Arrays类
    • Date和Calendar类
      • Date
      • Calendar
  • JAVA异常处理
    • 常见异常
    • 捕获异常
    • Throws 关键字
      • 自定义异常类
  • JAVA IO处理
    • 流的概念
    • 流的分类
      • 字节流
      • 字符流
    • 流的使用
      • 字节流使用
        • 对象流与序列化
      • 字符流使用
        • 字符流读取缓冲流
    • 文件夹操作
      • FileFilter接口
    • Properties
  • 参考文献
      • FileFilter接口
    • Properties
  • 参考文献

引言

学习一门编程语言不是一件难事,在本书的前言我要郑重强调一下这件事。学习如逆水行舟,不进则退;只要大家坚持,相信最后定会有所收获。本书作为一本入门的工具书,会侧重讲解JAVA的基础知识,旨在引导读者进入JAVA的学习大门。

什么是JAVA

JAVA是一种面向对象的高阶编程语言,在JAVA中有句老话:万物皆对象。对于java的介绍我引用百科的一些解释。(Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点 [2] 。Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等)

第一个JAVA程序

由于JAVA是一门面向对象的语言,在运行程序时我们需要单独建立一个类对象,在此类对象的main()函数中运行。废话不多说,直接上代码

public class hello_world
{public static void main(String[] args) {//这样我们就创立好了第一个程序的框架//在main函数里面,我们就可以书写一些需要的指令}
}

作为编程界的惯例,第一个程序当然是在console里面打印"Hello World"

public class hello_world
{public static void main(String[] args) {System.out.println("hello world");}
}

System.out.println() 是一条将程序中的数据打印在控制台,也就是console中的指令

在System.out.println后面有一对括号,在这个里面我们要传入想要打印在console中的内容,即函数的参数

因为要将”hello world“转化为计算机能看懂的语言,所以我们需要在"hello world"外加上双引号,将其转化为字符串类型

这样计算机就能读懂我们的语言,从而输出我们的指令。

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pfoSMW1z-1613061611808)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210128115153341.png)]


JAVA的数据类型

当我们运行JAVA程序时,我们会进行一系列的数学计算,此时拥有存贮数据的变量就尤为重要。在JAVA中为了拥有存储数据的变量,我们往往需要在内存中开辟一道空间,例如:

//在编辑器中的代码变量
int x =5;
int y =6;

//在内存中存储的变量数据, 变量名称我们可以自定义

JAVA的数据类型可以分为2大类

  1. 内置数据类型

  2. 引用数据类型

内置数据类型

Java 的内置数据类型一共有8种,8种中又可以分为4种。

  1. 整型: byte, short, int, long
  2. 浮点型: float, double
  3. 字符型: char
  4. 布尔型: boolean

整型

整型顾名思义,它是用来存储整数的

虽然byte, short, int和long都属于整型,但它们之间还是各有差异因为各自的取值不同。

数据类型 数据范围 数据大小(bit /位) 默认值
byte -128~127 (-2^7 ~(2^7)-1) 1 byte= 8 bits 0
short -32768~32767 (-2^15 ~(2^15)-1) 2 bytes = 16 bits 0
int -2^31 ~ (2^31)-1 4 bytes = 32 bits 0
long -2^63 ~(2^63)-1 8 bytes = 64 bits 0L

一般情况下,我们使用int类型来定义整数,因为int的范围足以满足我们日常的需求

byte a =100;short b = 10000;int c = 100000;long d =10000000;

浮点型

与整型恰好相反,浮点型是用来存储小数的。浮点型分为float和double,两者的区别在于精度。

数据类型 数据范围 数据大小(bit /位) 默认值
float (单精度浮点型) 1.4·10^-45 ~ 3.4·10^38 4 bytes = 32 bits 0.0f
double(双精度浮点型) 4.9·10^-324 ~ 1.7·10^308 8 bytes = 64 bits 0.0d

虽然说浮点数可以表示小数,但是浮点数不能表示精确的数,例如货币。如果需要表示精确的数,需要借助其他java类例如Big Decimal来实现。例子: 1.40* 165 = 231 但是 计算机给出的计算是230.999999999997

通常浮点数在未声明的前提下都是double类型,

float f1 = 234.5f;
double d1 = 123.4;

字符型

char类型是一个单一的16位Unicode字符, 表示字符时用单引号。char的范围是0~65535,大小为16 bits

数据类型 数据范围 数据大小(bit /位) 默认值
char(字符) 0~65535 2 bytes = 16 bits ‘u0000’

对char变量赋值既可以使用数字,也可以使用字符,char可以存储任何字符

public class test {public static void main(String[] args) {char a =65;char b ='A';System.out.println(a);System.out.println(b);}
}

结果

布尔型

布尔类型指true和false,boolean数据只表示1位信息,可作为标志flag来记录true或false

数据类型 数据范围 数据大小(bit /位) 默认值
boolean true / false 1 bit false

引用数据类型

  1. 数组
  2. 类与对象
  3. 字符串

下面有一张图来表示引用类型数据

这张图上p1,p2,p3,p4作为类对象,当他们被创建时,他们实际上时作为指针指向一些数据

在本节引用类型暂时提一下,在后面的章节中会详细解释这些

基础类型转换

在运行程序时,我们有时需要将不同类型的数据转化为同一类型

类型转换又可分为自动类型转换与强制类型转换

自动类型转换

自动转换条件是转换前数据类型的位数低于转换后数据类型的位数

转化过程中可能会有精度损失

byte , short , char 可自动转化为int

int 可转化为 long

long 可转化为 float

float 可转化为 double

public class test {public static void main(String[] args) {char a =65;int b = a;System.out.println(a);System.out.println(b);}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uWyg1G64-1613061611811)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210128175039057.png)]

强制类型转换

如果被转化数据类型位数大于要转化的数据类型的位数,此时需要用到强制类型转换,注意Boolean类型不能被强制转换

强制转换格式

public class test {public static void main(String[] args) {char a ='A';byte b = (byte)a; //强制将char类型转化为byte类型//其实将这些数据打印出来,也暗含了一层数据转换System.out.println(a);System.out.println(b);}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sf8WSxcn-1613061611813)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210128175841728.png)]


JAVA符号

既然JAVA作为一门计算机编程语言,它一定能像计算器一样为我们做一些运算,所以在本章我们将讲解JAVA的运算符号。

算数运算符

运算优先级和现实生活中一样,括号( ) > * 或 % 或 / > + 或 -

符号 含义 例子
= 赋值 int i =5; 把5赋值给i
+ 加号 int i = (5+6);
- 减号 int j = (6-1);
* 乘号 int k = (7*8);
/ 取整 int a = (7/8);
/ 除号 double c = 7.0 /8;
% 取余 int b = (7%8);
// 转义字符 写注释用的
public class test {public static void main(String[] args) {int i = 5+6;int j = 6-1;int k = 7*8;int a = 9 / 8;double b = 9.0 / 8;  //如果想用除法获得小数,必须要用double类型的数据int c = 9 % 8;System.out.println("5+6 = "+i);System.out.println("6-1 = "+j);System.out.println("7*8 = "+k);System.out.println("(整除)9/8 = "+a);System.out.println("(除以)9.0/8 = "+b);System.out.println("(取余)9%8 = "+c);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EfkgjWuS-1613061611814)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129202007447.png)]

//优先级测试
public class test {public static void main(String[] args) {double a = (2+1)+3.0/5-6*7-(4/3);System.out.println("(2+1)+3.0/5-6*7-(4/3) = "+a); //注意(4/3) 是取整,结果是1 }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ACH71YxL-1613061611816)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129202931197.png)]

关系运算符

在运行程序时,我们需要对一些数据进行判断,此时就需要关系运算符

关系运算符判断后,返回true 或 false

符号 含义 例子
== 等于 (6 == 7) false
!= 不等于 (6 != 7) true
> 大于 (6 > 7) false
< 小于 (6 < 7) true
<= 小于或等于 (6 <= 7) true
>= 大于或等于 (6 >= 7) false

逻辑运算符

和电路图中的逻辑门类似, 逻辑运算符就是

与, 或,非

A为true

B为false

符号 含义 例子
&& 与,and,当左边与右边同时为true时返回true (A && B) false
|| 或, or, 左边或右边任意一个满足即返回false (A||B) true
! 非,与所选的条件相反 !(A||B) false

补充

看别人的源码时有时会碰到以下的几种符号

符号 含义 例子
++ 加一 a++; a的值加1
减一 b–; b的值减1
+= 加等于 a += b; 意思是a= a + b;
-= 减等于 a -= b; 意思是 a = a -b;
/n 换行 “/n”
/t 水平制表符 从左往右数8个空格

JAVA逻辑判断

上文我们提到了逻辑运算符与关系运算符,这些符号会给我们返回boolean 类型的数据 :true 或 false

true / false便是用在逻辑判断中的

if / else

假如大家对其他语言,例如python有所了解, 判断通常会使用if else语句,格式如下

if(条件语句){//执行的指令
}
else if(条件语句){//执行的指令
}
//else指的是最终条件,即排除if与else if条件之后
else{//执行的指令
}

例子

在这个例子里面会用到用户输入指令,Scanner

import java.util.Scanner;
public class test {public static void main(String[] args) {Scanner input = new Scanner(System.in);  //创建scanner对象,这样就可以从控制台输入System.out.print("a: ");int a = input.nextInt(); //nextInt()指输入的值是int类型数据,该方法是通过对象调用,后面会讲System.out.print("b: ");int b = input.nextInt();//比较a与b的大小if(a>b) {System.out.println("a大于b");}else if(a<b) {System.out.println("a小于b");}else {System.out.println("a等于b");}input.close();}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j6heCkcD-1613061611817)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129210114533.png)]

除此之外,还有嵌套式的if else

if(a > b){if(a > c){//当a大于b 同时 a大于c时,打印"a is MAX"System.out.println("a is MAX");}else{System.out.println("b < a <c ");}
}

switch case

switch case 类似于条件判断,通过switch的判断来选取对应的case,格式如下

switch(condition){case value://actionbreak;case value2://actionbreak;default: //当case中的value没有一个满足condition时,default中的指令才会执行//action
}

例子

//输出输入数字所对应的英文(1-9)
import java.util.Scanner;
public class switch{public static void main(String[] args) {System.out.print("NUM: ");Scanner num = new Scanner(System.in);int digit = num.nextInt();String digitName; //String是字符串类型,属于引用数据类型,在后面有提到switch (digit) {case 1: digitName = "one"; break;case 2: digitName = "two"; break;case 3: digitName = "three"; break;case 4: digitName = "four"; break;case 5: digitName = "five"; break;case 6: digitName = "six"; break;case 7: digitName = "seven"; break;case 8: digitName = "eight"; break;case 9: digitName = "nine"; break; //有时为了节省空间,可以连在一起写default: digitName = "I cannot distinguish this number"; break;}System.out.print(digitName);num.close();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MZpyKBrc-1613061611819)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130101525956.png)]

每个case后面都跟有一个break,用于阻止case1中的action执行完毕后再执行case2的action

反例

import java.util.Scanner;
public class switch2{public static void main(String[] args) {System.out.print("NUM: ");Scanner num = new Scanner(System.in);int digit = num.nextInt();String digitName;switch (digit) {case 1: digitName = "one"; break;case 2: digitName = "two"; break;case 3: digitName = "three"; break;case 4: digitName = "four"; case 5: digitName = "five";case 6: digitName = "six"; break; case 7: digitName = "seven"; break;case 8: digitName = "eight"; break;case 9: digitName = "nine"; break;default: digitName = "I cannot distinguish this number"; break;}System.out.print(digitName);num.close();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hbcY1AyX-1613061611820)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130101720253.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ggRlfTKu-1613061611821)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130101740442.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DW41QtCF-1613061611822)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130101843945.png)]

由于没有在case 4和 case 5后面加上break, 无论输入的是4还是5,最终给予digitName的赋值始终是 “six”;

直白点说,break就是用来阻止程序继续向下运行的指令


JAVA循环

学完逻辑判断与基本的运算,接下来我们要了解一下java中的循环,

java的循环如同其他语言一样,包含

  1. for循环
  2. while循环
  3. do while循环

for循环

结构

for(初始值;循环结束条件;初始值变化){//action
}

在for循环中,初始值一般是我们自定义的,例子如下

//我们创造一个for循环,这个循环运行5次,每次打印我们定义的变量的值
for(int i=0;i<5;i++){System.out.println(i);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UxKmB9Ks-1613061611823)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130103416060.png)]

从输出的结果可以看出,当i的值等于5时,条件返回为false,循环终止

while循环

格式

//判断条件指的是满足这个条件时,程序循环运行
while(判断条件){//action
}

例子

//与上面for循环的案例类似
int i=0;
while(i <5) {System.out.println(i);i++; //前面计算符号补充部分有提及,i++指 i = i + 1
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e0XuzCEk-1613061611824)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130104404416.png)]

如果对这个不太明白,下面有一幅图可以解释

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-at8b94pM-1613061611825)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130105844321.png)]

总共运行了5次,在第6次时条件判断为false,所以循环停止

break

while循环还可以与之前switch case里面提到的break一起使用,例子如下

int i=0;
while(i < 7) {//当i 等于 5 时,循环中止if(i == 5) {break; //break的作用是中止循环}System.out.println(i);i++;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SRjU0ohf-1613061611826)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130111831321.png)]

continue

与break对应的是continue,break是中止循环

而continue是跳过这一轮循环将要执行的语句,直接进入下一轮循环,例子如下

public class test {public static void main(String[] args) {int i=0;while(i <7) {System.out.println(i);i++;//当i 等于 5时,跳过输出这一轮的 "--------"//由于i++放在前面,所以输出i后, i的值+1, 即在第5轮,输出i=4过后跳过输出 "--------"if(i == 5) {continue;}System.out.println("--------");}}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pjRHZxY4-1613061611827)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130112521021.png)]

do while循环

格式

do{//action
}while(判断条件);

do while循环和while循环的区别是:无论条件为何,do while循环都会将action部分执行一遍,例子如下

public class test {public static void main(String[] args) {int i=0;do {System.out.println(i);i++;}while(i<0);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LvRoK3o2-1613061611828)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130124327971.png)]


判断与循环的应用

前面几章我们学习了java的运算符,逻辑判断与循环,这一章举一些例子,灵活运用前面的知识

求最大公因数

题目:求出48与292的最大公因数与最小公倍数,

程序分析:使用辗转相除法

public class LargestFactor {public static void main(String[] args) {int m =48;int n = 292;int a = m;  int b = n;int r = a%b;while (r!=0) {a = b;b = r;r = a%b;}int divisor = b;    System.out.println("The Greatest Common Divisor:"+divisor);System.out.println("The Lowest Common Multiple:"+(m*n)/divisor);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S6scExTR-1613061611829)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130155438457.png)]

求100以内的素数

题目:输出100以内的素数?

程序分析:素数是大于1的正整数,只能除以它本身与1

public class isprime {public static void main(String[] args) {for(int i=2; i<=100; i++) {boolean isPrime = true;for (int j=2; j<i; j++) {if((i%j) == 0) {isPrime = false;break;}}if(isPrime) {System.out.println(i+" is prime");}}}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wZUo3rXp-1613061611829)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130143041470.png)]

不死神兔

题目:古典问题:有一对兔子,从出生后第3个月起都生一对兔子,小兔子长到第3个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子对数为多少(20个月内)?

程序分析:兔子的规律为数列1,1,2,3,5,8,13,21…(斐波那契数列)

public class Test{public static void main(String[] args){long a=1;long b=1;long c=0;System.out.print(a+"\t"+b);//for循环用来计数for(int i=3;i<=20;i++){//a,b,c交换数据c =a+b;a =b;b =c;System.out.print(c+"\t");}}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-URMRdTWP-1613061611830)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130140249510.png)]

水仙花数

题目:打印出1000以内的水仙花数,所谓的“水仙花数”是指一个三位数,其各位数字立方和等于该数本身。例如:152是一个“水仙花数”,因为153 =1的3次方+5的3次方+3的3次方。

程序分析:需要用到for循环,每个数分解出个位,十位,百位

public class flower {public static void main(String[] args) {//水仙花数是三位数,从100开始,到1000结束for(int i=100; i<1000; i++ ) {//第一种获取每位的方法int a = i/100;  //对i取整,获取百位的数字int b = (i-a*100)/10; // 减去1的百位上的数字,除以10,获取十位的数字int c = i-100*a-10*b; //个位就是排除十位与百位//第二种获取每位的方法//int a = i/100; //int b = (i%100)/10; //对i除以100取余,再通过10取整,获得百位//int c = (i%100)%10; //对i除以100取余,再通过10取余,获得个位int sum = a*a*a+b*b*b*b+c*c*c;if (sum==i) {System.out.println(i+"是水仙花数");}}System.out.println("Finish");}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XXBkYWV8-1613061611831)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130133328919.png)]

99乘法表

题目:输出9*9口诀

程序分析:嵌套式for循环,注意换行

public class test {public static void main(String[] args) {for(int i=1;i<=9;i++) {for(int j=1;j<=i;j++) {System.out.print(j+"*"+i+"="+(i*j)+"\t");}System.out.println();}}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eSlfSUmN-1613061611831)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130155506835.png)]

求Pi的值

题目:根据Gregory-Leibniz series, 我们可以计算Pi的值,要求算到第10000个级数

程序分析:Pi = (4/1) - (4/3) + (4/5) - (4/7) + (4/9) - (4/11) + (4/13) … 观察发现规律:分母为奇数,偶数-1,

public class test {public static void main(String[] args) {double rst=0.0;for(int i=1;i<=10000;i++){//判断是偶数还是奇数if(i%2==1){rst += 4.0/(2.0*i-1); //分母为奇数1,3,5,7……}else{rst -= 4.0/(2*i-1);}}System.out.println(rst);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EU9GcD7q-1613061611832)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130160022440.png)]


JAVA函数

函数,大家在初高中应该有所耳闻,例如f (x), f (x) 这个函数有名字f, 同时它也包含一个参数x。设置一个函数可以被我们连续调用,java或者说大部分主流的编程语言都继承了数学中函数的特点。

在本书的前面几章大家应该已经接触到了函数,System.out的println(""),这个就是一个系统类的函数(方法)

我们可以将想要打印在console(控制台)上的内容作为参数传入此函数(方法),它就将内容呈现出来

格式

java的函数(在类对象中也可以叫做方法)格式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bTA4Pg2Z-1613061611834)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130182507127.png)]

  • 函数返回值类型可以为任意数据类型,int, double, char, string等
  • public static 都是修饰符,在后卖会讲到
  • return 的值类型一定要与定义函数时一致

在函数或方法中参数还有另外一个名字,形参;而我们传入时的参数叫实参(实际的参数)

作用域

说到函数或方法,那一定要提及作用域,即我们创建的参数能够用在那些范围内

下面我们用一个例子来解释

public class test {public static void main(String[] args) {int a = 8;int b = 9;int c = add(a,b); //当要调用方法时,直接写该函数的名字与应该传入的参数System.out.println(a);System.out.println(b);System.out.println(c);}public static int add(int i, int j) {int a = i + j;return a;}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EZnODs2e-1613061611835)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130184251449.png)]

在上面的例子中,main主函数中的a, b, c是实参;而add函数中的i, j, a都是形参

我们可以看出虽然在main函数与add函数中a都是我们的参数,但是两者为什么都不冲突呢?

因为作用域的不同导致了两者的不同。在add函数中定义的参数的作用域仅仅在add函数中,不超过add,而main函数中定义的参数的作用域也仅仅在main中,无法扩散到add函数中。

假如main函数想要与add函数交换参数,就必须通过形参和return。

void关键字

有心的小伙伴也许已经发现了我们的main函数为什么没有返回值,且是返回值类型是void

void的英文意思是空,即什么也没有

同理,用在函数上时,表示该函数接收参数但不需要有返回值,这个函数就像一个方法一样,如下

//写一个比较大小的程序
public class test {public static void main(String[] args) {int a = 19;int b = 79;int c = 100;MAX(a, b, c); //此时调用MAX方法,没有返回值}public static void MAX(int a, int b, int c) {System.out.println("NUM: "+a+" "+b+" "+c);int max = a;if(a < b) {max =b;if(b < c) {max = c;}}System.out.println("MAX is "+max);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eQRe1Svh-1613061611836)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210130190143049.png)]

函数调用其他函数

我们在一个函数中可以调用别的函数,例子如下

public class test {public static void main(String[] args) {int a = 19;int b = 79;int c = 100;MAX(a, b, c);}public static void MAX(int a, int b, int c) {System.out.println("NUM: "+a+" "+b+" "+c);int max = a;if(a < b) {max =b;if(b < c) {max = c;}}print(max); //直接输入函数名与参数就可以使用该函数}//通过print函数我们把max的值打印出来    public static void print(int max) {System.out.println("MAX is "+max);}
}

JAVA数组

上文提到了引用类型数据,在本章我将讲解其中一个引用类型数据:数组

对C语言或其他编程语言有所了解的伙伴应该听说过数组这个定义。数组,顾名思义,是将一系列统一的数据放在一起的组合。比如我们想将 ‘h’,‘e’,‘l’,‘l’,‘o’ 这几个字符放在一起之后再使用,此时我们就需要创建一个 字符类型的数组。

为什么说数组是引用类型的呢?

当我们创立一个数组并赋予其值,并不是在内存中直接开辟含有这些数据的数组,而是将数组的指针指向这些数据。直白点说,数组就像浏览器中的收藏夹,我们需要点击哪个链接(数据)时,就打开这个收藏夹(数组)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9hiEMme8-1613061611837)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129163522377.png)]

以char类型的数组为例,接下来将介绍几种创建数组的方法

创建数组

//声明数组变量
char[] words;
char words[];//创建数组的几种方法
//1
//每一组括号前要先声明数组中存储数据的类型
words = new char[5]; //在后面的括号中放的数据是我们所定义的数组的大小//2
words2 = new char[5] //与上一个差不多
//当然声明与创建数组可以放在一起
char[] word = new char[5];//3
char[] words3 = {'h','e','l'.'l','o',};

当第1种和第2种数组创建完毕后,默认内部的5个元素都为’\u0000’(char 类型的默认值);

当第3种数组创建完毕后,默认的元素是初始化的那些元素

import java.util.Arrays;
public class test {public static void main(String[] args) {int[] words = new int[5];char words2[] = new char[5];char[] words3 = {'h','e','l','l','o'};//由于数组无法直接通过System.out.println打印出来,//我们需要调用Arrays包中的toString()方法System.out.println("words "+Arrays.toString(words));System.out.println("words2 "+Arrays.toString(words2));System.out.println("words3 "+Arrays.toString(words3));}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ougL3cAd-1613061611839)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129170236619.png)]

访问数组元素

创建数组是为了储存数据,所以我们应该要明白如何访问/调用数组中的元素

我们需要通过数组的下标来访问数组中的元素

在计算机编程语言中,数组下标几乎都是从0开始(数组中第一个元素),因为这样可以方便计算机的指针读取数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VPnPsy1p-1613061611840)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129172730705.png)]

所以数组中第一个元素下标是0,第二个元素下标是1,依次类推。注意最后一个元素的下标必须是(数组长度-1),因为元素下标是从0开始的。

public class array2{public static void main(String[] args) {double[] values = {2,3,4,5};double one = values[0]; //注意获取数组中元素,接收的变量类型应与数组一致double two = values[1];System.out.println(one);System.out.println(two);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6IIEPOJg-1613061611840)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129173312581.png)]

有心的同学应该注意到了,我们存进去的元素是整数类型,为什么最后打印出来是double呢?

因为在存入double类型数组中时,编译器进行了自动类型转换,将整型转化为浮点double类型

遍历数组

为了读取数组中的元素,我们通常使用遍历的方法

通过一组for循环来获取数组中的每个元素

public class array2{public static void main(String[] args) {double[] values = {2,3,4,5};//public int length;是java数组中自带的方法,用于返回该数组的长度for(int i=0;i<values.length;i++) {System.out.println(values[i]);}}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mNk9DjfS-1613061611840)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129174548429.png)]

我们还可以使用for-each(也叫增强for)来遍历数组

for(type element : array){System.out.println(element);
}

增强for允许我们在不访问下标的情况下读取数组,十分方便

public class array2{public static void main(String[] args) {double[] values = {2,3,4,5};for(double value: values) {System.out.println(value);}}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xbhNNukY-1613061611841)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129174548429.png)]

数组与函数

我们可以把数组作为一个返回值或参数放在函数中

将数组作为参数传入函数

public class array2{//add 将数组作为参数传入函数,返回数组中所有元素的和public static double add(double[] values) {double total = 0; for (double element : values){total = total + element;}return total;}public static void main(String[] args) {double[] values = {2,3,4,5};System.out.println(add(values));}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gzZI0CFL-1613061611842)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129184602683.png)]

将数组作为返回值输出

import java.util.Arrays;
//将输入数组每个元素加1,并返回
public class array2{public static double[] add(double[] values) {for(int i=0;i<values.length;i++) {values[i] += 1;}return values;}public static void main(String[] args) {double[] values = {2,3,4,5};System.out.println(Arrays.toString(add(values)));}
}

多维数组

我们的现实世界是由多个维度所组成,一条线是一维, 一个平面是二维,我们所在的空间是三维

和现实世界类似,数组也可以创造多个维度

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-26KDN6dx-1613061611843)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129185959447.png)]

创建二维数组或多维数组的方式与一维数组类似


public class test {public static void main(String[] args) {int[][] num = new int[2][3]; //创建一个2行3列的二维数组num[0][0] = 1; //给第一行,第一列的元素赋值为1num[1][0] = 2; //给第二行,第一列的元素赋值为2//因为是二维数组,通过两个for循环来遍历打印for(int i=0;i<num.length;i++) {//num.length是获取二维数组的行数for(int j=0;j<num[0].length;j++) {//num[0].length是获取第一行数组的个数,即num二维数组的列数System.out.print(num[i][j]+" ");}System.out.println();}}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DgaM6fUI-1613061611843)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210129191554891.png)]

在本章中我们有运用到一个数组的工具类, Arrays,在后面常用类中,我们会有详细的解释。

小案例 Tic-Tac-Toe (井字棋)

import java.util.Scanner;
public class TiTaTu{public static void main(String[] args) {//用二维数组模拟棋盘, 0和1代表O和Xint [][] array = {{0,1,0,1},{1,0,0,1},{1,1,1,1},{0,1,0,1},};boolean rst_X = false;boolean rst_O = false;int numOfX_S = 0;int numOfO_S = 0;int numOfX_RS = 0;int numOfO_RS = 0;int k = array.length -1;for(int n=0;n<array.length;n++) {int numOfX_H =0;int numOfO_H =0;for(int m=0;m<array[n].length;m++) {if(array[n][m] == 1) {numOfX_H++;if(numOfX_H == array.length ) {rst_X = true;}}else if(array[n][m] == 0){numOfO_H++;if(numOfO_H == array.length){rst_O = true;}}}if(array[n][n] == 1) {numOfX_S++;if(numOfX_S == array.length ) {rst_X = true;}}else if(array[n][n] == 0) {numOfO_S++;if(numOfO_S == array.length ) {rst_O = true;}}//reverse diagonal lineif(array[n][k] == 1) {numOfX_RS++;if(numOfX_RS == array.length ) {rst_X = true;}}else if(array[n][k] == 0) {numOfO_RS++;if(numOfO_RS == array.length ) {rst_O = true;}}k--;}if(rst_X == true) {System.out.print("X win");}else if(rst_O == true) {System.out.print("O win");}else {System.out.print("Equal");}}
}

案例2,打印二维数组初始值

public class Print2DArray{public static void PrintOut(int[][] array) {for(int i=0; i<array.length;i++) {for(int j=0;j<array[i].length;j++) {System.out.printf("%3d", array[i][j]);}System.out.println();}}public static void main(String[] args) {int[][] a = new int[5][5];PrintOut(a);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9gpzHDwx-1613061611845)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131235733815.png)]


JAVA类与对象

不知道大家以前有没有听说过这样一句话“万物皆对象”。这句话出自Think in Java,一本今典的java书籍。在java中,任何东西都可以被描述成一个类,且每个类都能被用来实例化对象;因为周围的世界是由各种各样的对象所构成,所以我们可以利用java来模拟我们周围的世界,创建各种各样的类例如:学生类,老师类,汽车类,飞机类。

对象创建

创建一个对象的前提是有这个对象的类,我们先创建一个Animal类

package Class_Study;
public class animal {private int age; //private是修饰符,后面会讲public animal(){//action 我们可以在这里添加一些指令}public animal(int num) {age = num;}public void roar() {System.out.println("I am yelling.");}
}

拥有了animal这个类后,我们就可以实例化(创建)一个animal对象

animal Tom = new animal();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5iOegIrB-1613061611846)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131105309311.png)]

以后要是想对animal对象进行一些操作,直接通过Tom调用animal的内部方法(长得像函数的东西)即可。

构造方法

在类中的函数统一称作“方法”

有人也许注意到了在animal类中为什么还有与animal同名的方法呢?

这些方法叫做构造方法,也称构造函数。

无参构造
public animal(){ //public是修饰符System.out.println("I am an animal."); //在无参构造方法里面,我们可以写一些指令
}

像这一个构造方法,就是无参构造方法,当我们实例化对象时,可以不需要添加参数

animal Tom = new animal();

假如我们书写的类中没有写构造方法,如下

package Class_Study;
public class animal {public void roar() {System.out.println("I am yelling.");}
}

此时,编译器会自动给我们加上一个无参构造方法,等同于这样

package Class_Study;
public class animal {public animal(){}public void roar() {System.out.println("I am yelling.");}
}
有参构造

有参构造方法就是在无参构造的基础上增添了参数,方便我们将外部的参数传递给实例化的对象

我们第一个实例化对象的例子中除了有无参构造方法,还有有参构造方法

public animal(int num) {age = num;  //将外部的参数num赋值给对象内部的ageSystem.out.println("My age is "+ age); //将age的值输出到控制台上
}

因为是有参构造方法,我们实例化时可以加参数

int age = 3;
animal Tom = new animal(age);
//由于作用域的不同,我们在main函数中定义的age并不与animal对象中的age相冲突

注意

当我们既没有写无参构造也没有写有参构造时,编译器会自动给我们加上一个无参构造方法。

但如果我们自己写了有参构造方法无参构造方法任意一个以后,编译器不会自动添加无参构造方法

对象方法

上面也提到了,在类对象中函数叫做方法method, 除了叫法不同,各种功能与函数一致

package Class_Study;
public class animal {private int age;public animal(){}public animal(int num) {age = num;System.out.println("My age is "+ age);}public void roar() {System.out.println("I am yelling.");}
}

在animal类中,roar就是对象方法。使用roar方法必须通过animal的实例化的对象来调用

public class animalTest {public static void main(String[] args) {animal Tom = new animal(3);Tom.roar();}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pGFaF1y5-1613061611847)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131113112130.png)]

因为在实例化过程中使用了有参构造方法,有参构造方法中有一行指令是打印age: "System.out.println("My age is “+ age);” 所以在控制台中出现 My age is 3

我们通过Tom来调用类方法

Tom.roar();

所以程序执行此方法,在控制台中打印 “I am yelling”

this关键字

this关键字可以用于在本类中调用,本类方法或实例变量; 它也可以用于调用本类中其他构造方法;

this可以理解为当前对象

一个一个分析;

  1. 实例变量

当我们方法中的形参与类对象中的参数名字一样时,使用this关键字可以避免运行时的error,如下

没有使用this 关键字时

public class animal {private int age;public animal(){System.out.println("I am an animal.");}public animal(int age) {age = age;}public void printAge() {System.out.println("My age is "+ age);}public void roar() {System.out.println("I am yelling.");}}
public class animalTest {public static void main(String[] args) {animal Tom = new animal(3);Tom.printAge();}
}

此时的编译器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EtV3iFye-1613061611848)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131115030599.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uVx1YGRR-1613061611849)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131184425189.png)]

为什么我们输的是3,而打印的却是0 ?因为我们并没有将值真正赋给对象的age

为了避免这种无效赋值的情况,我们需要使用this

this的作用相当于告诉编译器,你要把我传进的参数age赋值给类对象的age,然后调用类对象的age打印输出

public class animal {private int age;public animal(){System.out.println("I am an animal.");}public animal(int age) {this.age = age;}public void printAge() {System.out.println("My age is "+ this.age);}public void roar() {System.out.println("I am yelling.");}}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dchxMTLs-1613061611850)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131184639113.png)]

  1. 本类方法

为了表示方便,在本类中调用本类方法,可以在调用的方法前加上this

public class animal {private int age;public animal(){System.out.println("I am an animal.");}public animal(int age) {this.age = age;System.out.println("My age is "+ this.age);}public void roar() {System.out.println("I am yelling.");this.Hungry(); }public void Hungry() {System.out.println("I am hungry!!");}}

这个this加或不加都没关系,编译器会帮我们自动加上

  1. 调用本类的其他构造方法

this可以调用构造方法,这样能避免相同初始化代码

this()是用来调用无参构造方法的

没加this()

public class animal {private int age;public animal(){System.out.println("I am an animal.");}public animal(int age) {this.age = age;}public void printAge() {System.out.println("My age is "+ this.age);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zvACJehR-1613061611851)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131185804560.png)]

加上this();

public class animal {private int age;public animal(){System.out.println("I am an animal.");}public animal(int age) {this(); //必须方法构造方法最前面this.age = age;}public void printAge() {System.out.println("My age is "+ this.age);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZwmzIw2j-1613061611852)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131185909356.png)]

可见,加上this()就调用了animal的无参构造方法

注意,this();必须在调用的方法最前面

this(a); 可以调用有参构造方法, a是有参构造需要的参数,例子如下

public class animal {private int age;public animal(){this(3);System.out.println("I am an animal.");}public animal(int age) {this.age = age;}public void printAge() {System.out.println("My age is "+ this.age);}
}
//测试类
public class animalTest {public static void main(String[] args) {animal Tom = new animal();Tom.printAge();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-apcvmb6p-1613061611853)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131190535142.png)]

我们直接调用animal的无参构造,但是age是有初始值的,就是我们在无参构造中this(3);传入的age。

方法重载Overload

方法可以重载,当然之前学习的函数也可以重载;重载后的方法可以接收不同参数

所谓的重载Overload针对同一个类,在这个类里面可以包含名字相同但是接收参数不同的的方法。例子如下。


public class animal {private int age;public animal(){System.out.println("I am an animal.");}public animal(int age) {this();this.age = age;}public void printAge() {System.out.println("My age is "+ this.age);}//对printAge进行Overloadpublic void printAge(int year) {this.age += year;System.out.println("After "+year+" years. My age is "+this.age);}
}

public class animalTest {public static void main(String[] args) {animal Tom = new animal(3);Tom.printAge();Tom.printAge(4);}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9I3kwb1h-1613061611854)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131195018061.png)]

其实方法的重载就像无参构造方法与有参构造方法一样

对象封装

封装,顾名思义将数据封起来,不让外界轻易访问。在java开发时,我们有时不希望外界访问或改变我们设计好的数据,此时需要将这些数据封装起来。

为了封装数据,我们需要一些访问修饰符,例如public, private(这些在前面大家应该已经遇到了,但是不知道是什么)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vVjr7yf7-1613061611855)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131201852288.png)]

一般用访问修饰符时,都用public 或 private ,public定义的数据都可以访问,但是private的只有本类才能访问

封装可以使数据更安全,假如说想要获取或改变数据,可以使用get, set, 例子如下

public int getAge() {return age;
}
public void setAge(int age) {//有set的好处就是,假设在给age赋值时传入的时string类型或其他类型,set里面可以加上判断this.age = age;
}

对象继承

介绍

聊完上面几章,我们进入对象中比较重要的环节,对象继承,这就像儿子与父亲一样,所以被继承的类大家称为父类,继承的类称之为子类

子类对于父类的继承

  1. 子类继承父类所有public方法与属性, 也可以添加自己独有的方法
  2. JAVA继承遵循单一继承关系, 即一个子类只能继承一个父类
  3. 当子类添加自己方法时可以对父类方法进行覆盖, override。 例如父类可以使用a方法,子类继承a方法,可以再写一遍a方法,使a方法实现另一种
//继承语法: class B extends A{      } //B是子类, A是父类, 子类继承父类

例子

package Class_Study;
//animal是父类
public class animal {private int age;public animal(){System.out.println("I am an animal.");}public animal(int age) {this.age = age;System.out.println("My age is "+ this.age);}public void roar() {System.out.println("I am yelling.");}}
package Class_Study;public class TestForAnimal {public static void main(String[] args) {Dog kit = new Dog();kit.roar();}
}
class Dog extends animal{Dog(){System.out.println("I am a dog.");}//方法覆盖overridepublic void roar() {//super.roar();这个super关键字后面再讲System.out.println("I am hungry. I need meat");}
}

在实例化子类对象时,我们会先调用父类的默认构造方法,再调用子类的构造方法,

这就是为什么会出现"I am an animal"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zzGaJQ6b-1613061611856)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210131234622162.png)]

在上面这个例子中,dog类是animal类的子类,它继承了父类的方法

Dog kit = new Dog(); //实例化子类对象,调用子类的无参构造方法

在具有继承关系的创建中,系统先创建父类再创建子类。 如果有默认的构造方法, 先调用父类A的默认无参构方法,再调用子类B的所属构造方法。 这就是为什么我们调用dog类的无参构造方法时,先打印“I am an animal.”,再打印“I am a dog.”

//方法覆盖overridepublic void roar() {System.out.println("I am hungry. I need meat");}

在子类中,子类拥有与父类相同的方法,这样可以对父类的方法进行覆盖,(方法的Override必须是方法一样)(即访问修饰符+返回值类型+名称+传入参数类型一样)

多态

世间万物都有属于自己的类,这些类之间又可以进行分类,例如汽车,飞机等可以被分在(继承)交通工具类里面;老师,学生,家长可以被分在(继承)人这个类里面。我们可以用交通工具类或人类来作为汽车或学生宽泛的表示方法。

  1. 使用父类作为方法形参实现多态, 使方法参数类型更为宽泛
  2. 使用父类作为方法返回值实现多态, 使方法可以返回不同子类对象

例子: A a = new B(); A是B的父类

使用多态时,只能使用父类的方法或子类覆盖父类的方法, 例如

//例子
package Class_Study;public class animal {private int age;public animal(){System.out.println("I am an animal.");}public animal(int age) {this.age = age;System.out.println("My age is "+ this.age);}public void roar() {System.out.println("I am yelling.");}}
package Class_Study;public class TestForAnimal {public static void main(String[] args) {animal kit = new Dog();kit.roar(); // 作为父类的kit只能调用子类覆盖后的方法或自己本身的方法}
}
class Dog extends animal{ //狗类继承了父类animal类,覆盖了roar()这个方法Dog(){System.out.println("I am a dog.");}//方法覆盖overridepublic void roar() {System.out.println("I am hungry. I need meat");}public void run() {System.out.println("I can use four legs to run!!");}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R2PomW1Q-1613061611856)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202104457940.png)]

假设我们作为父类,再调用子类的方法,例如这个:用kit animal类调用dog子类的run方法,出现错误

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I5o8Lhwj-1613061611857)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202104550114.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OCuMepQD-1613061611858)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202104646229.png)]

向上转型

格式

//Animal类是Dog类的父类
Animal a = new Dog()

刚才上面那个例子就使用了向上转型的方法(子类转为父类)。

向下转型

向下转型前提是 原来实例是子类(先向上转型):

Animal a = new Dog()
Dog dog = (Dog) a //利用强转向下转型

多态的好处是有很强的扩展性,例如这样

speak(new Cat());
speak(new Dog());//此时我们将cat类与dog类作为参数传进去
public void speak(Animal a){a.roar(); //函数会自动向上转型,调用cat与dog类中Override父类Animal的roar方法
}
instanceof关键字

向下转型前,应判断引用中对象的真实类型,以达到准确性

语法, (dog instanceof animal)//返回结果为boolean

if (args instanceof type) {type new_name = (type) args;
}
package Class_Study;public class TestForAnimal {public static void main(String[] args) {animal animal = new Dog();if (animal instanceof Dog) { //判断animal的真实类型是否是Dog类,是的话进行向下转型Dog dog = (Dog) aanimal;dog.run();}}
}class Dog extends animal{Dog(){System.out.println("I am a dog.");}//方法重写overridepublic void roar() {System.out.println("I am hungry. I need meat");}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xQxxYVnP-1613061611859)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202115137520.png)]

super关键字

作为子类,我们继承了父类的方法,但当我们继承父类后并Override父类方法后,我们就不能再使用父类的方法,为了能再次使用,我们需要使用super关键字

和this()一样,super()必须是第一条语句

可以调用父类的属性和方法

super.upload() // 父类的方法
super.value //父类的属性,注意这个属性必须是public公共属性,私有属性无法继承

例子,调用父类属性

public class Value {public static void main(String[] args) {B b =new B();b.print();}
}
class A{int value =10;
}class B extends A{int value = 20;public void print() {int value =30;System.out.println(value);  //就近原则,选取本方法中的valueSystem.out.println(this.value); //this调用本类中的valueSystem.out.println(super.value);//super调用父类中的value}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rhj3h0qR-1613061611859)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202121542748.png)]

例子,调用父类的方法

package Class_Study;
//父类
public class animal {private int age;public animal(){}public animal(int age) {this.age = age;System.out.println("My age is "+ this.age);}public void roar() {System.out.println("I am yelling.");}}
package Class_Study;
//子类
public class TestForAnimal {public static void main(String[] args) {Dog dog = new Dog();dog.roar(); }
}class Dog extends animal{Dog(){System.out.println("I am a dog.");}//方法重写overridepublic void roar() {super.roar(); //通过super调用父类的roar方法System.out.println("I am hungry. I need meat");}public void run() {System.out.println("I can use four legs to run!!");}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ObOJS1cO-1613061611860)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202122338431.png)]

super也可以调用父类构造方法

super() // 调用无参构造方法
super(5, 6) //调用有参构造方法

在继承章节开头我们碰见的那个例子里面,当调用我们调用子类构造方法时,系统会自动调用父类的无参构造方法,即在子类无参构造之前加上super();如下

package Class_Study;
//父类
public class animal {private int age;public animal(){//父类的无参构造System.out.println("I am an animal.");}public animal(int age) {this.age = age;System.out.println("My age is "+ this.age);}public void roar() {System.out.println("I am yelling.");}}
package Class_Study;
//子类
public class TestForAnimal {public static void main(String[] args) {Dog dog = new Dog();}
}class Dog extends animal{Dog(){super();System.out.println("I am a dog.");}//方法重写overridepublic void roar() {super.roar();System.out.println("I am hungry. I need meat");}public void run() {System.out.println("I can use four legs to run!!");}
}

加上super()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Ggqw58j-1613061611862)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202122732411.png)]

没加super()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gnFoirY4-1613061611862)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202122802897.png)]

编译器默认调父类无参构造方法(在没加super()的前提下),不管子类调用的是否是无参还是有参构造

当C对象继承B对象,B对象继承A对象时,实例化C对象,先调用A的无参构造,然后调用B的无参构造,最后调用C的无参构造

//子类调用父类的有参构造
Dog(){super(3); //在Dog子类的无参构造方法中,调用父类的有参构造System.out.println("I am a dog.");
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ZfTYONx-1613061611862)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202123738106.png)]

对象是引用类型

为什么说对象是引用类型?

我们new一个对象,其实是用一个指针指向这个部分数据集合,例子如下

//创建一个Point类,有x,y值
public class Point {private int x;private int y;public void SetPoint(int x, int y){this.x =x;this.y =y;}public void show() {System.out.println("("+this.x+" , "+this.y+")");}
}

public class TestPoint {public static void main(String[] args) {//实例化一个Point类Point a = new Point();//将a点的地址传入SetPoint函数SetPoint(a);//如果对象不是引用类型,a点的x,y值就不会改变a.show();}public static void SetPoint(Point b) {b.SetPoint(5, 5);}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ko0rP80P-1613061611862)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202215944627.png)]

上面例子的box diagram

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HQCsyKc1-1613061611863)(C:\Users\23881\OneDrive - Rose-Hulman Institute of Technology\未命名.jpg)]

包装类

由于基本类型不是对象,在万物皆对象的JAVA中,我们有时需要将这些数据封装成对象,这就是包装类

基本数据 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

基本类型封装的好处

  1. 方便进行对象操作
  2. 便于数据与字符串之间的转换

例如:将数字1转为字符串1,再将字符串1转为数字1

public class NumDemo1
{public static void main(String[] args) {int i =1;//把基本数据int封装成IntegerInteger num = new Integer(i);//数字转为字符串String word = num.toString();//打印转成的类型System.out.println(word.getClass());//将字符串转为数字,打印转成的类型System.out.println(Integer.valueOf(word).getClass());}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ikgqHyJ3-1613061611864)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210209194231137.png)]

JAVA字符串

在前面大家已经不止一次接触到了字符串String类型数据,String字符串是一个功能强大的类,它可以将多个字符放在一起,如下

char word = 'h';
String words = "hello world";

字符串与字符有一点区别:字符串内容放在双引号内,而字符则是单引号。

特点

  1. 字符串是常量,创建后不可改变
  2. 字符串字面值储存在字符串池中,可以共享
  3. String str = new String(“Java”)在堆里面创建一个对象

常用方法

public int length() //返回字符串长度
public char charAt(int index) //根据下标获取字符
public boolean contains(String str) //判断当前字符串是否包含传进去的字符str
public int indexOf(String str)//查找str首次出现的下标,存在则返回该下标,不存在则返回-1
public int lastIndexOf(String str)//查找字符串当中最后出现的下标索引
public String trim()//去除字符串前后的空格
public String toUpperCase()//全部转为大写
public boolean endWith(String str)//判断字符串是否是以str结尾
public boolean startWith(String str)//同样,也有以str开头的判断
public String replace(char oldChar, char newChar)//将原来旧的字符串替换为新的字符串
public String concat(String s)//返回连接后的字符串, s是加在后面的字符串
public String substring(int beginIndex, int endIndex)//返回一个分割过后的字符串
public char[] toCharArray()//将字符串转换成数组
Arrays.toString(char[] string)//为了将数组内的字符打印出来,调用Arrays工具类

下面用一串代码来演示如何使用这些方法

package StringStudy;import java.util.Arrays;//为了把数组中的内容转成字符串并打印出来public class Demo1 {public static void main(String[] args) {String words = "hello";System.out.println(words);words = "world";System.out.println(words);String str = new String("Java");String str2 = new String("Java");System.out.println("str与str2是否在同一地址:"+(str == str2));System.out.println("str与str2是否内容完全相同"+str.equals(str2));System.out.println("words在第一个的字符串是:"+words.charAt(0));System.out.println("将words转化为数组后的   Array:"+Arrays.toString(words.toCharArray()));System.out.println("将words转化为数组后的Array[0]:"+words.toCharArray()[0]);System.out.println("判断words中是否含有w:"+words.contains("w"));System.out.println("判断words中是否含有wd:"+words.contains("wd"));System.out.println("返回对应字符串rd的下标:"+words.indexOf("rd"));words = "hello";System.out.println("返回对应字符串l的下标:"+words.indexOf("l"));System.out.println("返回对应字符串l最后的下标:"+words.lastIndexOf("l"));String student = " Peter Bear ";System.out.println("After deleting SPACE in String----"+student.trim()+"----");System.out.println("将字母全部改为大写:"+student.toUpperCase());System.out.println("将原来的字符串中的内容进行替换:"+student.replace("ear", "ear is 18 years old."));String website = "www.peterbear.com";System.out.println("返回在原来的字符串后面增添内容的字符出:"+student.concat("'s website: ").concat(website));}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SPyl6PwK-1613061611865)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210202231723332.png)]

JAVA修饰符

再类对象封装中我们提到的private, public属于JAVA的访问修饰符;在本章我们将介绍其他的修饰符:非访问修饰符

static

static中文翻译是静态,所以关于static 的方法和属性叫做静态属性和静态方法

使用静态修饰符后程序会发生哪些变化?

  1. 静态属性和方法利用类名进行调用(假如说一个类仅含有static成员,那么这个类被称作工具类)

  2. 静态成员是全类所共享的成员

  3. static 关键字用来声明独立于对象的静态变量(静态属性),无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量。

//静态属性
static int count=10;

例子如下

package modifier;
//创建一个类,这个类有静态属性与非静态属性,含静态方法与非静态方法
public class StaticStudy {public int cnt=0; //非静态属性public static int cnt2=0; //静态属性,静态变量public void add() {cnt++;}public static void add2() {cnt2++;}public void show() {//因为静态成员是全类所共享的成员,所以非静态方法可以调用静态成员变量System.out.println("非静态计数器"+cnt);System.out.println("静态计数器: "+cnt2);}
}
package modifier;public class TestStatic {public static void main(String[] args) {StaticStudy num = new StaticStudy();//实例化一个类对象num.show();//初始值,调用show非静态方法num.add();StaticStudy.add2();//通过类名调用静态方法num.show();//add后的值System.out.println("类名调用静态属性: "+StaticStudy.cnt2);//类名调用静态属性System.out.println("----实例化第二个对象"+"----");StaticStudy num2 = new StaticStudy();//再实例化一个类对象num2.add();StaticStudy.add2();num2.show();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3pDt1S75-1613061611866)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203133932014.png)]

从上面例子我们不难发现无论一个类实例化多少对象,它的静态变量只有一份拷贝。

静态方法

特点

  1. 静态方法可以直接访问静态成员
private static int cnt3=0;
public static int cnt2=0; //静态属性,静态变量
public static void add2() { //静态方法给cnt2加一cnt2++;}
  1. 但是静态方法不能直接访问非静态成员

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sc5hPlgF-1613061611867)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203125411520.png)]

  1. 静态方法不能使用this和super关键字

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ARoVq8mg-1613061611867)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203134731231.png)]

  1. 静态方法不能重写,只能继承,没有多态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PGG1TWGV-1613061611868)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203135945647.png)]

静态代码块

static{      }
//整个程序执行过程中,只执行一次
//可以执行一些必要的初始化行为//与其相反的是非静态代码块
{}

静态代码块中只能放静态成员

系统初始化过程:静态代码块---->main函数---->非静态代码块---->构造函数

这里请参考下面的链接

静态类

倘若一个类是静态的,它一定是静态内部类//这个在讲到内部类的时候再具体分析

final

final意为最终的,最后的,即不可变的

最终类

final修饰的不能被继承, 例如String, Math,System类,这些类的均无法被继承

当FinalStudy准备继承Point类时,由于Point类是被final修饰,所以无法被继承

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-op8xRSgo-1613061611868)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203144245874.png)]

最终变量

final int num = 10;
final static string address = "school";

只能被赋值一次(常量)
1. 在构造方法中赋值
如果有一个对常量赋值,其他的构造方法都要对其进行赋值
2. 创建常量时直接赋值

我们创建了一个Point类,使用final修饰了原点,当我们想要改变原点数据时,失败

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jvHcb2d3-1613061611870)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203145808713.png)]

对于最终变量有两种初始化方法,

第一种:直接创建时就赋值

final int Origion_x=0;
final int Origion_y=0;

第二种:使用代码块进行赋值

final int Origion_x;
final int Origion_y;
{Origion_x=0;Origion_y=0;
}

第三种:在构造方法中

final int Origion_x;
final int Origion_y;
Point(){Origion_x=0;Origion_y=0;
}

倘若变量用static + final修饰,为静态常量,初始化要在静态代码块中进行

第一种:直接创建时就赋值

static final int Origion_x=0;
static final int Origion_y=0;

第二种:使用代码块进行赋值

static final int Origion_x;
static final int Origion_y;
static{Origion_x=0;Origion_y=0;
}

最终方法

不能被子类覆盖或者重写,只能继承

我们给父类的Print方法加上final修饰后,子类FinalStudy无法Override Print方法,所以只能继承该方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zfanjxGD-1613061611870)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203144655295.png)]

例子如下

package modifier;public class FinalStudy extends Point{}class Point{private int x;private int y;public void SetPoint(int x, int y) {this.x =x;this.y =y;}public final void Print() {System.out.println("( "+this.x+", "+this.y+" )");}
}
package modifier;
//测试
public class TestFinal {public static void main(String[] args) {FinalStudy point = new FinalStudy();point.SetPoint(1, 2);point.Print();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jlc1QG5v-1613061611871)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203145143119.png)]

对象常量

final修饰基本类型:值不可变

final 修饰引用类型:地址不可改变

例子如下

class Point{private int x;private int y;static final int Origion_x;static final int Origion_y;static{Origion_x=0;Origion_y=0;}public void SetPoint(int x, int y) {this.x =x;this.y =y;}public void Print() {System.out.println("原点: "+"( "+Origion_x+", "+Origion_y+" )");System.out.println("( "+this.x+", "+this.y+" )");}
}
package modifier;import java.util.Arrays;public class TestFinal {public static void main(String[] args) {final int[] nums = new int[] {1,3,5,7};System.out.println(Arrays.toString(nums));
//      nums = new int[] {5,6,7};//此时不能对nums再进行赋值,因为已经nums已经变成了常量nums[0] = 9; //但是nums内部的数据可以进行更改,因为nums是引用类型System.out.println(Arrays.toString(nums));final Point p1 = new Point();p1.SetPoint(6, 6);p1.Print();p1.SetPoint(10, 10);p1.Print();}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vMvOHovl-1613061611871)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203154357345.png)]

abstract

abstract中文意思是抽象,抽象即为不具体

抽象类

一个类不能同时被abstract和final修饰

当类对象没有具体的含义,可以将该类改为抽象类

例如Animal类,它本身没有任何意义各种方法比较抽象,但是继承Animal类的子类Dog类和Cat类有意义,所以要把Animal类改为抽象类

作用

  1. 可以被子类继承,提供共性的属性和方法
  2. 可以声明为引用,更自然的使用多态

抽象类当中可以包含抽象方法,也可以包含非抽象方法

//语法:
public abstract class Animal{  }

如果一个类被改为抽象类,该类就不可以被实例化, 即不能new 对象;但是我们能够用这个类来作为引用,就像多态向上转型一样

下面是一个关于抽象类的例子

package modifier;public class TestAbstract {public static void main(String[] args) {Dog dog = new Dog();dog.speak();Animal bird = new Bird(); //可以声明为引用,更自然的使用多态bird.speak();//dog和bird调用父类的walk方法dog.walk();bird.walk();}
}abstract class Animal{public abstract void speak();public abstract void move();//抽象类中包含非抽象方法public void walk() {System.out.println("I am walking");}
}class Dog extends Animal{@Overridepublic void speak() {System.out.println("Wang Wang Wang……");}@Overridepublic void move() {System.out.println("Dog uses his four legs to run");}
}class Bird extends Animal{@Overridepublic void speak() {System.out.println("Yin Yin Yin……");}@Overridepublic void move() {// TODO Auto-generated method stub}}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5xEga0Yh-1613061611872)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203162947766.png)]

抽象方法

一但类当中包含抽象方法,此类必须是抽象类

父类对象的方法本身没有意义,但为了实现多态(向上转型)又不得不保留

Animal dog = new Dog();
dog.eat();

抽象方法只有方法的声明,没有方法实现,此外抽象方法只能在抽象类当中

//格式
public abstract void eat();

子类继承父类,子类必须重写父类的抽象方法,否则子类必须是抽象类

//抽象的felid猫科动物类继承抽象的动物类,其中增添了抽象的猫科动物捕猎方法
abstract class felid extends Animal{abstract void hunt();
}

抽象类与抽象方法的小案例:

建立一个Vehicle的交通工具抽象类和一个主人类,打印主人回家时开的什么车,是什么品牌

package Polymophic_And_Abstract;public class Master {private final String name; //将主人的名字封装起来public Master(String name) {this.name = name;}public String getName() {return name;}public void GoHome(Vehicle vehicle) {System.out.println(this.getName()+"回家了");vehicle.run();}
}
package Polymophic_And_Abstract;public class TestForVehicle {public static void main(String[] args) {Master jim = new Master("Jim");Vehicle car = new Car("奔驰");jim.GoHome(car);}
}//创建一个抽象的Vehicle类
abstract class Vehicle {private final String band;public Vehicle(String band) {this.band = band;}public String getBand() {return band;}//一个抽象方法public abstract void run();}
//Car继承抽象的Vehicle交通工具类
class Car extends Vehicle{public Car(String band) {super(band);}
//implements 实现run()方法@Overridepublic void run() {System.out.println(super.getBand()+"牌的车在路上跑");}}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LD8zFs2k-1613061611872)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203170116415.png)]

JAVA接口

介绍

接口相当于是特殊的抽象类,定义方法,组成部分与抽象类类似

接口没有构造方法,所以不能创建对象但是可以implements,一个类可以实现多个接口,例如

C extends A implements B implements C

接口也可以和父类一样实现多态(向上转型)
仅可调用接口中实现的方法,不能调用实例化对象所独有的方法

接口往往可以代表一种能力,一但类对象实现了该接口,它也具备了这种能力

实现接口时,访问修饰符必须是public

接口与抽象类相同之处:

  1. 可编译成字节码文件
  2. 不能创建对象
  3. 可以作为引用类型 // 当作为引用类型时,仅可调用实现了的接口;
  4. 具有Object类中定义的方法(Object类是所有类对象的父类)

不同之处:

  1. 接口所有属性都是用public static final修饰
  2. 接口所有方法都是用public abstract 修饰
  3. 接口没有构造方法,动态代码块和静态代码块

类无法使用多继承,但是接口可以实现多继承接口

package Interface;public interface Ability extends flyable, swimmable{public abstract void fire();
}interface flyable{public abstract void fly();
}interface swimmable{public abstract void swim();
}

interface关键字

类对象是class,而接口则是interface

public interface A{ public static final String  FIELD = "Value"  public abstract void method();
}

注意

接口只能定义:公开静态常量 和***公开抽象方法***

public static final String FIELD="Value"; //公开静态常量,使用时,直接用接口进行调用
public abstract void method();//公开抽象方法只用写返回值类型和方法名

类一但implement就必须实现覆盖接口中全部抽象方法,此类就是该接口的实现类

补充

标记接口,例如Serializable接口

public interface Serializable{}; //表示实现这个接口的对象可以被序列化和克隆
public interface Cloneable{};

案例

  1. 给人实现飞的能力
//先创建fly的接口
package Interface;public interface fly {public abstract void fly();
}
//然后创建一个人类,来实现fly接口
package Interface;public class Person implements fly{String name;int age;Person(String name, int age){this.name= name;this.age = age;}public void eat() {System.out.println(this.name+" 在吃饭……");}public void sleep() {System.out.println(this.name+" 在睡觉……");}//由于继承了接口,我们必须实现接口的方法@Overridepublic void fly() {System.out.println(this.name+" can fly");}
}
//写一个测试类
package Interface;public class TestPerson {public static void main(String[] args) {Person jim = new Person("Jim",20);jim.fly();//利用接口作为引用类型fly baby = new Person("baby", 30);baby.fly();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BKnAsRfa-1613061611874)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203194232960.png)]

  1. USB案例

USB接口是大家熟知的一种接口,风扇,U盘,都是USB接口,我们要将USB接口插入电脑

//1先创建USB接口
package USB_Interface;public interface USB {public abstract void Service();
}
//2实现Fan,U盘的接口
//U盘
public class USB_Flash implements USB {@Overridepublic void Service() {System.out.println("USB-Flash has connected to the computer");}}
//风扇
public class Fan implements USB{@Overridepublic void Service() {System.out.println("Fan starts to run");}}
//3由于我们要将U盘和风扇插入电脑中,所以要创建一个电脑类
package USB_Interface;public class Computer {private USB usb1;private USB usb2;public USB getUsb1() {return usb1;}public void setUsb1(USB usb1) {this.usb1 = usb1;}public USB getUsb2() {return usb2;}public void setUsb2(USB usb2) {this.usb2 = usb2;}public void Run() {System.out.println("Computer starts to work!!");if(this.getUsb1() != null) {usb1.Service();}if(this.getUsb2() != null) {usb2.Service();}}}
//4最终的测试类
package USB_Interface;public class Test_USB {public static void main(String[] args) {Computer Windows = new Computer();Windows.setUsb1(new Fan());Windows.setUsb2(new USB_Flash());Windows.Run();}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3MSfafuL-1613061611874)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210203200029587.png)]

JAVA内部类

创建在类内部的类叫做内部类,

class Outer{//外部类class Inner{//内部类}
}

内部类拥有和普通类一样的属性,可以拥有方法,能够去实现接口,继承

如果外部类与内部类成员属性名字相同,则优先访问内部类成员
如果想要访问同名外部类成员,需要先写上外部类名字,再this.name,或直接Outer.this.name

既然已经有了外部类,那为什么还要内部类呢?

好处

  1. 内部类可以对外部类全部内容进行访问
  2. 方便访问外部类的私有属性(内部类可直接访问外部类的私有成员而不破坏封装)

成员内部类

package InnerClass;import InnerClass.OuterClass.InnerClass;public class NormalInnerTest {public static void main(String[] args) {//1. 第一种实例化内部类的方法//OuterClass outer = new OuterClass();//InnerClass inner = outer.new InnerClass();//2. 第二种实例化内部类的方法,一步到位InnerClass inner = new OuterClass().new InnerClass();inner.print();}
}class OuterClass{private String words="Outer Class";class InnerClass{public void print() {System.out.println(OuterClass.this.words);new OuterClass().print();System.out.println("Inner Class: Hello World");}}public void print() {System.out.println(words+": Hello World");}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hkMTS7sx-1613061611875)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210204213254151.png)]

成员内部类不能定义静态成员

静态内部类

静态内部类可以不依赖外部类对象实例化对象

只有静态内部类可以用static修饰

//实例化静态内部类
Outer.Inner StaticInnerDemo =new Outer.Inner();

案例

package InnerClass;class Outer{//外部类中包含静态成员变量与非静态成员变量private static String inf = "Hello World";private String inf2 = "GoodBye World";//创建静态内部类public static class Inner{//静态内部类里面包含静态方法与非静态方法private static void print() {System.out.println("\t静态成员变量: "+inf);//静态内部类无法直接调用非静态变量
//          System.out.println(inf2);
//由于外部类成员变量为私有,需要借助外部类来访问Outer out = new Outer(); System.out.println("\t非静态成员变量: "+out.inf2);}//非静态方法public void print2() {System.out.println("\t非静态方法调用静态成员变量: "+inf);}}//普通内部类public  class Inner2{//普通成员内部类无法创建静态方法public void print() { //但是可以调用外部类中的静态成员变量System.out.println("\t静态成员变量: "+inf);System.out.println("\t非静态成员变量: "+inf2);}}//外部类能够创建非静态方法public void fun() {//在外部类的方法中实例化内部类Inner innerDemo = new Inner();System.out.println("静态内部类的静态方法");//直接通过内部类类名访问静态方法Inner.print();System.out.println("静态内部类的非静态方法");//访问内部类非静态方法需要通过实例化的对象来访问innerDemo.print2();}}
public class InnerClassDemo1 {public static void main(String[] args) {//实例化静态内部类Outer.Inner StaticInnerDemo =new Outer.Inner();//实例化普通内部类Outer shell = new Outer();shell.print();Outer.Inner2 NormalInnerDemo = shell.new Inner2();System.out.println("静态内部类的非静态方法");StaticInnerDemo.print2();System.out.println("普通内部类的方法");NormalInnerDemo.print();}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-470Blw7C-1613061611875)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210204215906597.png)]

局部内部类

把一个类定义在方法内部,这个类叫做局部内部类,就像定义在方法中的变量叫局部变量一样

局部内部类不能定义访问修饰符,即不能定义为static

但是可以包含静态常量,private final static int count =2000;

public void fun(final String temp){class Inner{public void print(){System.out.println(info);System.out.println(temp);}}//实例化内部类,调用内部类方法new Inner().print();
}

匿名内部类

在java中处理内部类之外,还有一种匿名内部类。

匿名内部类就是指没有一个具体名称的类,此概念是在接口和抽象类的应用上发展起来的,

有时这种类只用一次,命名又可惜,所以就使用匿名内部类

以之前写的Ability接口为例

//接口
package InnerClass;public interface Ability extends flyable{public abstract void swim();
}interface flyable{public abstract void fly();
}
package InnerClass;import Interface.Ability;public class AnonymousInnerClass {public static void main(String[] args) {Ability SuperMan = new Ability(){@Overridepublic void swim() {// TODO Auto-generated method stubSystem.out.println("I can swim");}@Overridepublic void fly() {// TODO Auto-generated method stubSystem.out.println("I can fly");}};SuperMan.swim();SuperMan.fly();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fPyxVxD5-1613061611875)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210204225913164.png)]

使用匿名内部类时,必须继承一个父类或实现一个接口

JAVA泛型

JAVA泛型英文generics,

本质是参数化类型,就是把类型作为参数传递,泛型对象不能被实例化:T type = new T();

这么说大家估计还是觉得这个定义比较抽象,

举个例子:我们要写一个排序方法,这个方法能够对int类型,String类型,double类型都进行排序,此时要使用泛型方法

泛型可以提高代码的重复性,防止类型转换异常,提高代码的安全性

泛型字母含义

E - Element:指集合中的元素

T - Type:Java类型,种类

K - Key:键

V - Value:值

N - Number:数值类型

格式

<T,...> //T是类型占位符,是一种引用类型

泛型方法

泛型方法可以接收不同类型的参数,根据传进去的参数做适当的处理,格式如下

//<T> 声明此方法为泛型方法, T指出返回值是泛型T
//Class<T> 指明泛型T的具体类型, c用来创建泛型T代表的类对象
public <T> T getObject(Class<T> c){//创建一个泛型对象T t = c.newInstance();return t;
}

例子,有三个不同类型的数组,分别打印出其中的值

package GenericsStudy;public class GenericDemo1 {//泛型方法public static < E > void printArray(E [] inputArray) {//输出数组元素for (E element : inputArray) {System.out.printf("%s ", element);}System.out.println();}public static void main(String[] args) {//创建不同类型数组Integer[] intArray = {1, 2, 3, 4, 5};Double[] doubleArray = {1.1, 2.2, 3.3, 4.4};Character[] charArray = {'H', 'E', 'L','L','O'};System.out.println("整型数组元素为:");//因为是写在本类里面,所以可以直接调用//如果是测试类写在本类外面,需要通过类名来调用静态方法,printArray(intArray);System.out.println("\n双精度型数组元素:");printArray(doubleArray);System.out.println("\n字符串数组元素:");printArray(charArray);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bNTFMXgx-1613061611876)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210205114935980.png)]

案例2

编写一个add方法,传入不同类型的数字类型,并返回相加的值,相加的值是double类型

package GenericsStudy;public class GenericsDemo5 {//extends是为了做泛型界定,即泛型T必须是Number的子类public static <T extends Number> double add(T num1, T num2) {double sum=0.0;sum = num1.doubleValue() + num2.doubleValue();return sum;}public static void main(String[] args) {System.out.println("double 类型相加:5.5 + 6.7 ="+add(5.5, 6.7));System.out.println("int 类型相加:5 + 7 ="+add(5, 7));System.out.println("double 与 int 类型相加:5.5+6 ="+add(5.5, 6));}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h5bQ1WUk-1613061611876)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210205211611985.png)]

泛型类

既然方法可以定义为泛型,类也可以定义成泛型

泛型类中可以包含泛型方法,多个类型参数

package GenericsStudy;public class GenericDemo3<T> {private T t;public void add(T t) {this.t = t;}public T get() {return this.t;}public static void main(String[] args) {GenericDemo3<Integer> one = new GenericDemo3<Integer>();GenericDemo3<String> two = new GenericDemo3<String>();one.add(1);two.add("Hello World");System.out.println(one.get());System.out.println(two.get());}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I2ZSAv5l-1613061611877)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210205214226660.png)]

上面提到了,泛型可以存储多个类型,下面我们来写一个简易字典,仅包含一对key和value

package GenericsStudy;public class GenericDemo6 {public static void main(String[] args) {Dictionary<String, Integer> dic1 = new Dictionary<String, Integer>();dic1.put("Peter",110);System.out.println(dic1.getKey());System.out.println(dic1.getValue());System.out.println(dic1.getAll());}
}class Dictionary<K, V>{private K key;private V value;public void put(K key, V value) {this.key = key;this.value = value;}//获取keypublic K getKey() {return key;}//获取valuepublic V getValue() {return value;}//获取key与value的字符串public String getAll() {return key.toString()+":"+value.toString();}}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fJEknvNO-1613061611878)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210205215953250.png)]

泛型接口

继承了泛型接口的类会变成泛型类

package GenericsStudy;public class GenericDemo7 {public static void main(String[] args) {ImpleData<String> Imple = new ImpleData<String>();Imple.print("Hello World");}
}//创建一个泛型接口
interface  Data<T>{T getData(T t1);
}//ImpleData实现了Data接口
class ImpleData<T> implements Data<T>{@Overridepublic T getData(T t1) {return t1;}public void print(T t1) {System.out.println("Print: "+this.getData(t1));}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S8qvVnlv-1613061611879)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210205221855579.png)]

通配符

通配符是指这个 问号:?,

List <?> seq = new ArrayList<>();

  • <? extends T>表示该通配符所代表的类型是T类型的子类。

? extends通常与List一起用,List是一种存储数据的容器和Array数组类似,在后面的章节有介绍

package GenericsStudy;
import java.util.List;public class GenericDemo4 {public static void main(String[] args) {/*由于我们extends Number了,种类只能是Number类或Number的子类如果使用String类型,会报错  */List<Number> sequence = new ArrayList<>();sequence.add(1);sequence.add(2);sequence.add(1.4);sequence.add(7.9f);getDate(sequence);}public static void getDate(List<? extends Number> data) {for(Object i : data) {System.out.println(i);}}
}
  • <? super T>表示该通配符所代表的类型是T类型的父类。
  • 不能同时声明泛型通配符上界和下界

JAVA集合

我们Java后端一般要进行数据处理,假设所有数据都是储存在数组里面,大小长度受限,不方便;所以我们在本章将引进集合的概念,集合是对象的容器,定义了对多个对象进行操作的常用方法,可实现数组的功能,但比数组更灵活。注意:数组可以存储基本类型,如int,但是集合只能存储引用类型,如String,所以在集合中存数字时,要将int类型转化为Integer类型

对于集合中的元素我们想要遍历有2种方法

  1. 增强for(for each循环)
for(Object i :container1) {System.out.println(i);
}
  1. 通过迭代器来遍历
//迭代器是通过集合内部的方法来获得的
Iterator<Object> itr = container1.iterator();
//itr.hasNext()是判断是否还有下一个元素,如果是,该循环开始执行
while(itr.hasNext()) {//打印出下一个元素System.out.println(itr.next());
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5kVeBFEv-1613061611880)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210207164038116.png)]

Collection接口

Collection接口是众多集合的父接口,List接口,Set接口都是继承Collection接口,然后通过实现类实现其中的方法。由于Collection,Set, List都是接口,创建时必须要用实现类;比如List的实现类ArrayList,Set的实现类HashSet.

//引入集合模块
import java.util.Collection
//创建集合,由于Collection是接口,我们用Collection的实现类ArrayList来实现
//Collection集合是泛型集合,< >中我们要添加存储的数据类型, Object类是所有类的父类
Collection<Object> container1 = new ArrayList<>();

由于集合是无法储存基本类型的,当我们存入基本类型时,集合会自动装箱

list.add(20); 实际上是list.add(new Integer(20));

如果有一些方法解释不全,可以参考以下API链接

API: https://www.runoob.com/manual/jdk1.6/

常用方法 作用 例子
boolean add(E e) 添加元素,添加成功返回true container1.add(“apple”);
void clear() 移除collection中的所有元素 container1.clear();
int size() 返回集合中元素的个数 int size = container1.size();
boolean contains(Object o) 如果此 collection 包含指定的元素,则返回 true container1.contains(“apple”);
Iterator iterator() 返回collection的所有元素的迭代器 Iterator itr = container1.iterator();
boolean isEmpty() 判断此集合是否为空 container1.isEmpty();
boolean remove(Object o) 移除集合中的某对象 container1.remove(1);
Object[] toArray 将此集合转为数组 Object[ ] arrray = container1.toArray();

例子1

package CollectionStudy;import java.util.ArrayList;//引入ArrayList
import java.util.Collection;//引入Collection
import java.util.Iterator; //引入迭代器public class CollectionDemo1 {public static void main(String[] args) {//使用多态Collection<Object> container1 = new ArrayList<>();//添加元素container1.add("apple");container1.add(1);//增强for遍历元素System.out.println("----增强For----");for(Object i :container1) {System.out.println(i);}//迭代器遍历元素System.out.println("----Iterator----");Iterator<Object> itr = container1.iterator();  while(itr.hasNext()) {System.out.println(itr.next());}}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0fxJJdV0-1613061611880)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210207115019530.png)]

例子2

Collection集合可以存储其他引用数据类型,我们创建一个学生类,并将学生类添加进ArrayList集合(Collection的实现类)

package CollectionStudy;
//Students类
public class Students {private int age;private String name;public Students(int age, String name) {super();this.age = age;this.name = name;}public int getAge() {return age;}public String getName() {return name;}//重写toString方法,按照我们的规定返回字符串@Overridepublic String toString() {// TODO Auto-generated method stubreturn "Student [ name: "+this.getName()+", age: "+this.getAge()+"  ]";}
}
//测试类
package CollectionStudy;import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;public class CollectionDemo2 {public static void main(String[] args) {Students Tom = new Students(18, "Tom");Students Jimmy = new Students(22, "Jimmy"); //先实例化2个students对象Collection<Students> container = new ArrayList<Students>();container.add(Tom);container.add(Jimmy);//遍历 1for(Object student : container) {System.out.println(student);}System.out.println("\t----Line-----");//遍历 2Iterator<Students> itr = container.iterator();while(itr.hasNext()) {System.out.println(itr.next());}}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5vVj96uo-1613061611881)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210207165739022.png)]

我们想用集合的contains方法,来判断是否包含某引用元素

Students Jimmy = new Students(22, "Jimmy");
Collection<Students> container = new ArrayList<Students>();
container.add(Jimmy);
System.out.println(container.contains(Jimmy));

结果是:true

假设我们传进去的不是Jimmy,而是: new Students(22, “Jimmy”)

结果是:false

为了避免这个问题,我们需要重写students类中的equals方法

//在Students类中重写此方法   @Overridepublic boolean equals(Object obj) {if(this == obj) {return true;}if(obj == null) {return false;}if(obj instanceof Students) {Students students = (Students) obj;if(this.name.equals(students.name)&&this.age == students.age) {return true;}}return false;}

再次调用测试类

结果为:true

List接口

List是有序(添加顺序与遍历顺序一致),有下标,元素可重复的集合

List的独有方法

如果有一些方法解释不全,可以参考以下API链接

API: https://www.runoob.com/manual/jdk1.6/

方法 解释 例子
void add(int index, Object o) 在index位置插入对象o conatiner2.add(0, “Hello”);
boolean addAll(int index, Collection c) 将一个集合元素增添到index位置 container2.addAll(0,container1);
Object get(int index) 返回集合中指定位置的元素 container2.get(0);
List subList(int fromIndex, int toIndex) 返回fromIndex与toIndex之间的元素 container2.subList(0, 5);
ArrayList

ArrayList是由数组结构实现的,查询快,增删慢

增添包:import java.util.ArrayList;

构造方法:ArrayList container = new ArrayList<>();
E为泛型即ArrayList可以增添任何类

常用方法 解释
public boolean add(E e); 添加元素
public E get(int index) 按照索引获取元素,从0开始
public E set(int index, E element) 可以替换指定元素
public boolean remove(Object 0) 根据内容删除元素
public E remove(int index) 根据index删除元素,返回删除元素

例子

我们要创建一个Students类,将几个students对象存入ArrayList类中

package CollectionStudy;public class Students {private int age;private String name;public Students(int age, String name) {super();this.age = age;this.name = name;}public int getAge() {return age;}public String getName() {return name;}@Overridepublic String toString() {// TODO Auto-generated method stubreturn "Student [ name: "+this.getName()+", age: "+this.getAge()+"  ]";}}
package CollectionStudy;import java.util.ArrayList;
import java.util.Arrays;public class ArrayListCollection {public static void main(String[] args) {ArrayList<Students> container = new ArrayList<>();Students Jim = new Students(18, "Jim");Students Tom = new Students(20, "Tom");//成功add元素后,返回是否成功System.out.println("是否增添了Jim:"+container.add(Jim));container.add(Tom);System.out.println("获取第一个元素:"+container.get(0));//把第2个元素设置为Alexcontainer.set(1, new Students(78, "Alex"));System.out.println("第2个元素是:"+container.get(1));//container包含的元素个数System.out.println("元素个数:"+container.size());//将ArrayList转化为数组Object[] array = container.toArray();System.out.println("将ArrayList转化为数组:"+Arrays.toString(array));//删除元素,删除Jim的信息System.out.println("删除: "+container.remove(Jim));System.out.println("删除后个数:"+container.size());}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f4FSI5pI-1613061611882)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208192224042.png)]

假如我们增添,删除时用的不是Jim, 而是new Students(18, “Jim”); ?

package CollectionStudy;import java.util.ArrayList;
import java.util.Arrays;public class ArrayListCollection {public static void main(String[] args) {ArrayList<Students> container = new ArrayList<>();Students Jim = new Students(18, "Jim");
//      Students Tom = new Students(20, "Tom");System.out.println("是否增添了Jim:"+container.add(Jim));container.add(new Students(20, "Tom"));System.out.println("获取第一个元素:"+container.get(0));//把第2个元素设置为Alexcontainer.set(1, new Students(78, "Alex"));System.out.println("第2个元素是:"+container.get(1));//container包含的元素个数System.out.println("元素个数:"+container.size());//将ArrayList转化为数组Object[] array = container.toArray();System.out.println("将ArrayList转化为数组:"+Arrays.toString(array));//删除元素,注意,此时我们new Students(18,"Jim");System.out.println("删除: "+container.remove(new Students(18, "Jim")));System.out.println("删除后个数:"+container.size());}
}

结果

即使我们删除new Students(18,“Jim”);(内容相同),但是还是无法完全删除,删除返回为false

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Aiks5UEV-1613061611882)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208192723418.png)]

所以此时我们需要重写Students里面的equals方法(ArrayList判断remove时调用的方法)

 @Overridepublic boolean equals(Object obj) {if(this == obj) {return true;}if(obj == null) {return false;}if(obj instanceof Students) {Students students = (Students) obj;if(this.name.equals(students.name)&&this.age == students.age) {return true;}}return false;}

结果,成功删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CODsJJaJ-1613061611883)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208193019582.png)]

LinkedList

Link意思为链,链表集合就像所以数据被链子连接在一起一样

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T7g0GKYZ-1613061611884)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208193746827.png)]

特点:链表结构实现,增删快,查询慢

使用方法与ArrayList类似

例子

继续用LinkedList存储Students类的信息

同样,我们先不重写equals方法

package CollectionStudy;public class Students {private int age;private String name;public Students(int age, String name) {super();this.age = age;this.name = name;}public int getAge() {return age;}public String getName() {return name;}@Overridepublic String toString() {// TODO Auto-generated method stubreturn "Student [ name: "+this.getName()+", age: "+this.getAge()+"  ]";}}
package CollectionStudy;import java.util.LinkedList;public class LinkedListDemo1 {public static void main(String[] args) {LinkedList<Students> container = new LinkedList<>();System.out.println("增添Tom: "+container.add(new Students(20, "Tom")));container.add(new Students(18, "Jim"));//pop从container中弹出元素System.out.println("Pop第一个元素:"+container.pop());container.add(new Students(18, "Jim")); container.add(new Students(72,"Trump"));System.out.println("删除元素Jim:"+container.remove(new Students(18, "Jim")));//遍历for(Object i :container) {System.out.println(i);}}
}

结果Jim无法被删除,同时***我们还发现List可以存储相同的元素***

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vsjNqaj3-1613061611885)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208200323333.png)]

此时,我们再重写Students的equals方法

 @Overridepublic boolean equals(Object obj) {if(this == obj) {return true;}if(obj == null) {return false;}if(obj instanceof Students) {Students students = (Students) obj;if(this.name.equals(students.name)&&this.age == students.age) {return true;}}return false;}

结果,成功删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dNaB7hId-1613061611885)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208200612292.png)]

Set接口

上文我们介绍了List接口与其的实现类,现在我们开始讲Set接口

Set是无序(添加顺序与遍历顺序不一致),无下标,***元素不可重复***的集合

但是使用new可以插入内容相同的元素,因为Set判断的依据是equals方法,如果equals方法未重写则根据地址判断.

例子引入

package setStudy;import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;public class SetIntroduction {public static void main(String[] args) {//我们使用Set集合的实现类HashSet来创建集合Set<Object> container = new HashSet<>();container.add("Hello");container.add("World");container.add("Hello");container.add("My Friend");Iterator<Object> itr = container.iterator();while(itr.hasNext()) {System.out.println(itr.next());}}
}

这里由于是字符串,系统内部有equals方法,所以第二个"Hello"无法加入Set集合

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rxbghmdD-1613061611886)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208202251947.png)]

HashSet

HashSet是Set集合的一个实现类

存储结构:哈希表(数组+链表+红黑树)

存储过程

(1)根据hashcode计算保存的位置,如果此位置为空,则直接保存,如果不为空,则执行第二步

(2) 再执行equals方法,如果equals方法为true,则认为重复,否则形成链表,即添加到HashSet容器中

因为HashSet是以equal与hashcode进行比较,所以要重写hashcode与equals,这样就可以排除new的干扰。

构造方法

//E为任意种类的数据
HashSet<E> container = new HashSet<>();

基本操作与List / Set / Collection类似

增添元素:add(E e);

删除元素:remove(E e);

也有迭代器:Iterator iterator();

package setStudy;import java.util.HashSet;public class HashSetStudy {public static void main(String[] args) {HashSet<String> container = new HashSet<>();container.add("tim");container.add("Ketty");container.add("Yellow");System.out.println("HashSet中的内容:"+container.toString());System.out.println("HashSet的大小:"+container.size());System.out.println("此HashSet中是否含有Ketty数据:"+container.contains("Ketty"));}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YvBItWvM-1613061611887)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208203127750.png)]

案例2

像ArrayList一样,我们创建Students类,增添Students元素

package setStudy;public class Students {private int age;private String name;public Students(int age, String name) {super();this.age = age;this.name = name;}public int getAge() {return age;}public String getName() {return name;}@Overridepublic String toString() {return "Student [ name: "+this.getName()+", age: "+this.getAge()+"  ]";}
}
package setStudy;import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;public class HashSetDemo2 {public static void main(String[] args) {HashSet<Object> container = new HashSet<>();System.out.println("添加成功:"+container.add(new Students(18, "Jim")));System.out.println("添加成功:"+container.add(new Students(19, "Jone")));System.out.println("添加成功:"+container.add(new Students(18, "Alex")));System.out.println("添加成功:"+container.add(new Students(18, "Jim")));Iterator<Object> itr = container.iterator();while(itr.hasNext()) {System.out.println(itr.next());}}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-INqkJjIu-1613061611888)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208204141673.png)]

当我们增添内容相同的元素new Students(18, “Jim”)时,系统先判断是否是同一地址,如果没有看是否重写了equals和hashcode方法。因为判断地址不一样又没重写equals方法(照系统默认的equals方法),所以添加成功

现在我们重写Students类的equals和hashcode方法

 @Overridepublic boolean equals(Object obj) {if(this == obj) {return true;}if(obj == null) {return false;}if(obj instanceof Students) {Students students = (Students) obj;if(this.name.equals(students.name)&&this.age == students.age) {return true;}}return false;}@Overridepublic int hashCode() {//第一种转换string的方法
//      String age = String.valueOf(this.age);//第二种
//      String age = this.age+"";String age = Integer.toString(this.age);return age.hashCode()*this.name.hashCode();}

结果,相同内容的数据添加失败

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GX7opgtZ-1613061611888)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208204223172.png)]

TreeSet

实现Set接口的还有一个类,TreeSet,基于排列顺序实现元素不重复

此实现为基本操作(addremovecontains

实现了SortedSet接口,对集合元素自动排序

传入TreeSet的元素对象类型必须实现Comparable接口(指定排序规则)

因为TreeSet是通过ComparaTo方法确认是否为重复元素,所以可以通过内部类来override比较方法

使用TreeSet时,最好不要用Object类

package setStudy;import java.util.TreeSet;public class TreeSetStudy {public static void main(String[] args) {TreeSet<String> container = new TreeSet<>();container.add("Hello");container.add("xyz");container.add("world");container.add("hello");container.add("99");System.out.println(container.toString());}
}

String类型,(0,1,2…)默认数字在前–>大写–>小写(a,b,c…z)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qX8419Ic-1613061611889)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208204509037.png)]

案例2

还是Students的案例

package setStudy;public class Students {private int age;private String name;public Students(int age, String name) {super();this.age = age;this.name = name;}public int getAge() {return age;}public String getName() {return name;}@Overridepublic String toString() {return "Student [ name: "+this.getName()+", age: "+this.getAge()+"  ]";}
}
package setStudy;import java.util.Iterator;
import java.util.TreeSet;public class TreeSetStudy {public static void main(String[] args) {TreeSet<Students> container = new TreeSet<>();System.out.println("添加成功:"+container.add(new Students(18, "Jim")));System.out.println("添加成功:"+container.add(new Students(19, "Jone")));System.out.println("添加成功:"+container.add(new Students(18, "Alex")));System.out.println("添加成功:"+container.add(new Students(18, "Jim")));//遍历Iterator<Students> itr = container.iterator();while(itr.hasNext()) {System.out.println(itr.next());}}
}

由于我们再Students类中没有重写CompareTo方法,报错

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NIbDItbe-1613061611890)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208205925362.png)]

继承Comparable接口重写CompareTo方法

package setStudy;public class Students implements Comparable<Object>{private int age;private String name;public Students(int age, String name) {super();this.age = age;this.name = name;}public int getAge() {return age;}public String getName() {return name;}@Overridepublic String toString() {// TODO Auto-generated method stubreturn "Student [ name: "+this.getName()+", age: "+this.getAge()+"  ]";}@Overridepublic int compareTo(Object obj) {Students stu = (Students) obj;return (stu.name.hashCode() - this.name.hashCode());}}

此时TreeSet根据我们重写的compareTo方法来判断Object是否重复,我们的判断依据是students的名字的hashcode。

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9iik1hVF-1613061611890)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208211200435.png)]

Map接口

Map是一种将Key与value(键对象与值对象)相互映射的集合

Key Value
1 Biden
2 Trump

有时能用Map就不要用List,查找信息Map使用效率有时比List要高

//通过HashMap这个实现类来创建一个Map对象
//Students是传入Key的类型, String是value的类型
Map<Students, String> container = new HashMap<>();
常用方法 解释
V put(K key, V value) 放入键值对
Object get(Object Key) 通过key来获取值value
Set KeySet() 返回所有的Key的Set集合
Collection values() 返回包含所有值的collection集合
boolean containsKey(Object key) 如果此映射包含对于指定键的映射关系,则返回 true
boolean containsValue(Object Value) 如果此映射将一个或多个键映射到指定值,则返回 true
V remove(Object key) 如果存在,根据key移除此键值对

如果有一些方法解释不全,可以参考以下API链接

API: https://www.runoob.com/manual/jdk1.6/

实现Map接口的类有HashMap, TreeMap等

Map遍历

  1. KeySet()
Map <String, String> map = new HashMap<>();
Set<String> key = map.KeySet(); //是所有的Key的集合. 随后可以使用增强for 或迭代器去遍历
System.out.println("\tKeySet");
for( Students i : container.keySet() )
{System.out.println(i.getName()+"----"+container.get(i));
}
  1. EntrySet()

EntrySet()的效率要略高于KeySet()

for(Entry<Students, String> i :container.entrySet())
{System.out.println(i.getKey().getName()+"----"+i.getValue());
}

HashMap

HashMap和HashSet类似,也是存储数据的集合;HashSet是存储值数据,而HashMap是存储键值对数据

在HashMap中Key的数据是根据hashcode来存的

HashMap是无序的,即我们插入和取出的顺序是不一样的

Students案例

由于是根据hashcode来存储key,我们需要重写students中的hashcode和equals方法

package Map_Key_Value;public class Students {private int age;private String name;public Students(int age, String name) {super();this.age = age;this.name = name;}public int getAge() {return age;}public String getName() {return name;}@Overridepublic String toString() {// TODO Auto-generated method stubreturn "Student [ name: "+this.getName()+", age: "+this.getAge()+"  ]";}@Overridepublic boolean equals(Object obj) {if(this == obj) {return true;}if(obj == null) {return false;}if(obj instanceof Students) {Students students = (Students) obj;if(this.name.equals(students.name)&&this.age == students.age) {return true;}}return false;}@Overridepublic int hashCode() {// TODO Auto-generated method stub//第一种转换string的方法
//      String age = String.valueOf(this.age);//第二种
//      String age = this.age+"";String age = Integer.toString(this.age);return age.hashCode()*this.name.hashCode();}}
package Map_Key_Value;import java.util.HashMap;
import java.util.Map.Entry;public class OriginalMap {public static void main(String[] args) {HashMap<Students, String> container = new HashMap<>();
//      Students Jim = new Students(18, "Jim");
//      container.put(Jim, "CSSE120");container.put(new Students(18, "Jim"), "CSSE120");container.put(new Students(20, "John"), "CSSE220");container.put(new Students(17, "Alex"), "MA112");container.put(new Students(20, "Eric"), "ESL102");System.out.print("获取 Students(18, \"Jim\") 的值:");System.out.println(container.get(new Students(18, "Jim")));//get value//遍历//使用KeySet方法System.out.println("\tKeySet遍历");for(Students i:container.keySet()) {System.out.println(i.getName()+"----"+container.get(i));}//使用EntrySet方法System.out.println("\tEntrySet遍历");
//      Set<Map.Entry<Students, String>> entrys = container.entrySet();for(Entry<Students, String> i : container.entrySet()) {System.out.println(i.getKey().getName()+"----"+i.getValue());}}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rtUa3yt3-1613061611892)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210208215330562.png)]

TreeMap

TreeMap存储数据根据compareTo方法,对于自定义对象需要override比较方法,这个与TreeSet类似

下面就不多解释了,不懂可以查看API

API: https://www.runoob.com/manual/jdk1.6/

JAVA常用类

java中还有一些常用的工具类,这些类都是日常开发时可能会用到的

Arrays类

Arrays是数组的意思,Arrays是为数组所开发的工具类(方法是静态static方法)

arrays能处理的类型有int, double, long, char等

常用方法 解释
static boolean equals(int[ ] a, int[ ] a2) 如果两个int类型数组相等,则返回true
static int hashCode(int[ ] a) 返回指定数组的哈希值
static void sort(double[ ] a) 对指定数组进行升序排序
static String toString(char[ ] a) 将数组内容转化为字符串
static void sort(T[ ] a, Comparator<? super T> c ) 根据指定比较器的顺序对指定对象数组进行排序

Date和Calendar类

Data和Calendar是java中表示时间的两个类,它们能返回当前的时间的毫秒值

毫秒值表示自 1970 年 1 月 1 日 00:00:00 GMT 以来经过的毫秒数。

Date

构造方法

//以当前时间来初始化对象
Date date = new Date();//构造函数接收一个参数,这个参数是从1970年起的毫秒数
Date date = new Date(long millisec)
常用方法 解释
String toString() 格式化日期转义形式yyyy-mm-dd的日期
int getHours() 获取此刻的小时
String toLocaleString() 返回当前本地格式的时间(方法已过时)
package DateAndCalendar;
import java.util.Date;
public class DateDemo1 {public static void main(String[] args) {Date date = new Date();System.out.println(date.toString());System.out.println(date.toLocaleString());}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZHhV2f1Y-1613061611892)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210209130751457.png)]

我们可以使用SimpleDateFormat将日期输出格式化

格式 含义 例子
yyyy 2020
MM 1
dd 22
HH 24小时制 13
hh 12小时制 1
ss 07
S 毫秒 7000
E 星期几 Monday
D 一年中的第几天 365
F 一个月中的第几周的周几 2
w 一年中的第几周 7
W 一个月中的第几周 2
a AM / PM PM
z 时区 CST
package DateAndCalendar;
import java.text.SimpleDateFormat;
import java.util.Date;public class DateDemo1 {public static void main(String[] args) {Date date = new Date();
//      System.out.println(date.toString());
//      System.out.println(date.toLocaleString());SimpleDateFormat Df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(Df.format(date));}
}

我们还能用时间来做一个定时器

package DajavateAndCalendar;
//在10s之内,持续打印hello, 结束时打印world
public class DateDemo1 {public static void main(String[] args) {long start = System.currentTimeMillis();while(true) {long end = System.currentTimeMillis();if((end-start)>10000) {System.out.println("world");break;}System.out.println("hello");}}
}

Calendar

通过Calendar我们可以获取时间中特定的数据

Calendar类的功能要比Date类强大很多,而且在实现方式上也比Date类要复杂一些。

由于Calendar是protected类型,只能通过其他方法进行构建

static Calendar getInstance()
//使用默认时区获取日历Calendar date = Calendar.getInstance();

在Calendar中,系统定义了一些常量

Calendar.YEAR 年

Calendar.MONTH 月

Calendar.DATE 日期

Calendar.HOUR 小时

Calendar.MINUTE 分钟

Calendar.SECOND 秒

Calendar.DAY_OF_WEEK 星期几

常用方法

int get(int field)
calendar.get(Calendar.YEAR)//可用于获取calendar特定的年-月-日
abstract void add(int field, int amount) //根据日历给特定的字段增减时间量
void set(int year, int month, int day, int hourOfDay, int minute, int second)//设置特定值

例子

package DateAndCalendar;
import java.util.Calendar;
import java.util.Date;
public class CalendarDemo1 {public static void main(String[] args) {Calendar calendar = Calendar.getInstance();System.out.println(calendar.getTime());int year = calendar.get(Calendar.YEAR);int month = calendar.get(Calendar.MONTH)+1;int day = calendar.get(Calendar.DAY_OF_MONTH);System.out.println("Today is "+year+"-"+month+"-"+day);}
}

JAVA异常处理

在写程序时我们可能会遇到程序报错的情况,此时编译器会出现红色的提示,如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jgGqCjwp-1613061611893)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210209194701662.png)]

这就是异常Exception

所有的异常都是从java.lang.Exception中继承的,Exception类是Throwable类的子类,Throwable还有一个子类Error

常见异常

  1. 用户输入了非法数据
  2. 要打开的文件不存在
  3. 网络连接通信时中断,或者JVM内存溢出

三大类异常
1. 检查性异常(checked exception)
如用户输入异常或者打开一个不存在的文件(这些异常在编译时不能被简单地忽略)
2. 运行时异常
运行时可能被程序员避免的异常
3. 错误
错误不是异常,通常是摆脱程序员控制的问题,例如当内存溢出时,会报错误

检查性异常

  1. InterruptedException
    一个线程被另一个线程中断,抛出该异常。
  2. NoSuchFieldException
    请求的变量不存在

非检查性异常
1. ArithmeticException
2. NumberFormatException
当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常
3. NullPointerException
4. IndexOutOfBoundsException
遍历超过
5. UnsupportedOperationException

捕获异常

//捕获异常的基础语法
try{}catch(IOException e1){//如何处理该异常,异常e1的类型可以为Exception的子类或Exception;
}catch(ArithmeticException e2){}finally{//finally可加可不加//如果加了,无论是否发生异常,finally 代码块中的代码总会被执行。 //一般这里用于释放内存,如input.close()
}

例子

我们要用户输入两个数并互除,在除法中,被除数不能为0,所以我们要捕获这个异常

package Exception;import java.util.Scanner;public class ExceptionStudyDemo1 {public static void main(String[] args) {Scanner input = new Scanner(System.in);try {System.out.print("Num1: ");int num = input.nextInt();System.out.print("Num2: ");int num2 = input.nextInt();//注意此时num/num2得出的数字是整数System.out.println("Num1 / Num2 = "+num/num2);}catch(ArithmeticException a) {System.out.println(a.getMessage()); //获取为什么错误}finally {input.close();}}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HCb0goWT-1613061611894)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211155159674.png)]

解决方法

添加一个

double rst = num*1.0/num2;java
package Exception;import java.util.Scanner;public class ExceptionStudyDemo1 {public static void main(String[] args) {Scanner input = new Scanner(System.in);try {System.out.print("Num1: ");int num = input.nextInt();System.out.print("Num2: ");int num2 = input.nextInt();double rst = num*1.0/num2;System.out.println("Num1 / Num2 = "+rst);}catch(ArithmeticException a) {System.out.println(a.getMessage());}finally {input.close();}}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qNDO2WYq-1613061611895)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211155458450.png)]

Throws 关键字

throws中文意思是抛出,当一个函数有一个异常,此时我们不想处理时,我们可以throws这个Exception,交给函数外的部分处理

还是刚才num / num2的例子

package Exception;import java.util.Scanner;public class ExceptionStudyDemo1 {public static void main(String[] args) {Scanner input = new Scanner(System.in);try {System.out.print("Num1: ");int num = input.nextInt();System.out.print("Num2: ");int num2 = input.nextInt();divide(num, num2);}catch(ArithmeticException a) {System.out.println(a.getMessage());}finally {input.close();}}public static void divide(int num, int num2) throws ArithmeticException{System.out.println("Num1 / Num2 = "+num/num2);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VOPcrIp5-1613061611895)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211160006853.png)]

自定义异常类

所有异常必须是Throwable的子类。如果希望写一个检查性异常,则需要继承Exception类;如果是运行时异常,则继承RuntimeException类
继承语法

class CustomException extends Exception{  //里面根据编译器自动生成
}package Exception;
import java.util.Scanner;
public class ExceptionStudyDemo1 {public static void main(String[] args) {Scanner input = new Scanner(System.in);try {System.out.print("Num1: ");int num = input.nextInt();System.out.print("Num2: ");int num2 = input.nextInt();divide(num, num2);}catch(CustomException a){  //捕获自定义异常 }
public static void divide(int num, int num2) throws CustomException{ //在方法中抛出异常if(num2 == 0) {throw new CustomException(); //在方法中加入此语句,即为判断那种情况下抛出自定义异常}}
}

自定义异常有什么用呢?

当我们自己开发时,有时需要自己定义一些异常(别人能看懂的异常类名字),这样可以方便开发

JAVA IO处理

我们每次运行一个程序,此时我们输入的数据仅仅是存在缓存中的,倘若我们关掉程序,数据就会随之消失。为了把数据存起来,我们需要学习IO处理(Input Output),这样数据才可以写入内存硬盘里面。

流的概念

流stream可以为数据与目的之间建立通道。通过流我们可以把在内存中的信息写入到硬盘中;同理,我们也可以将硬盘中的数据读取,print在控制台里面
通过流读取的不管是字节还是字符,一般返回的都是int值

流的分类

流有很多种类,按照处理数据侧重点的不同可以分为输入/输出字节流与输入/输出字符流;

这里我引用某位博主的图片来解释:https://blog.csdn.net/mu_wind/article/details/108674284

字节流

字节流每次读取或写入一个字节,2字符=1字节, 1字节(Byte) = 8位 (bit)。字节流可以处理图像,视频等

一般英文字母一个字母为一个字节(字节是以int类型表示而字母则是以char类型表示)

字符流

字符流每次读取或写入一个字符。字符流只能用于处理文字信息

中文与英文有点区别,1个中文代表1个字符(char),1个字符 = 2个字节, 加入用字节流读取中文字符会出现乱码

流的使用

字节流使用

输入字节流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wjOhF8K1-1613061611896)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211224816778.png)]

//实例化对象
FileInputStream file = new FileInputStream("E:\\java程序\\ReadFile.txt");//读取文件内容
//读取出来的是字节流信息,要转化成char或string才能打印
//file.read()一次读取一个字节,如果有返回此字节,若没有返回-1
int data;
while((data = file.read()) != -1) {System.out.print((char)data);
}//使用自制缓冲区读取数据
byte[] buffer = new byte[3];//自制的一次能储存3个字节的缓冲区
int count=0;
while((count = file.read(buffer))!=-1) {System.out.print(new String(buffer,0,count));
}//注意打开的文件使用后要关闭
file.close();

输出字节流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DSBb74TV-1613061611898)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211224920029.png)]

//实例化对象
//true表示如果给出的文件地址已存在,则在此文件的基础上再写如内容
FileOutputStream Out = new FileOutputStream("E:\\java程序\\OutPutFile.txt",true);//写入内容
String words = "HELLO WORLD ";
Out.write(words.getBytes()); //通过字节流来写入,必须是字节形式//同样,写完记得关闭
Out.close();

由于普通的输入输出字节流效率不高,一般需要与缓冲流相互配合

文件内容先读入缓冲区,接着被程序访问,这样可以减少程序访问硬盘的次数

缓冲输入输出流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tZ7vrIER-1613061611899)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211225026578.png)]

//使用缓冲区读取数据
FileInputStream file = new FileInputStream("E:\\java程序\\ReadFile.txt");
BufferedInputStream buf = new BufferedInputStream(file);
int data;
while((data = buf.read()) != -1) {System.out.print((char)data);
}//缓冲区用完也最好记得关闭
buf.close();
//使用缓冲区输出数据
package IOStudy;import java.io.BufferedOutputStream;
import java.io.FileOutputStream;public class buf {public static void main(String[] args) throws Exception {System.out.println("hello world");FileOutputStream file = new FileOutputStream("E:\\java程序\\BufferOutput.txt",true);BufferedOutputStream buf = new BufferedOutputStream(file);for(int i=0;i<4;i++) {buf.write("hello world ".getBytes());buf.flush(); //使用缓冲区每写入一次数据要刷新一遍}System.out.println("Finish");buf.close();}
}
对象流与序列化

字节流可以传输任何数据类型,包括对象,由此产生了另一个流,对象流

创建方法

ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream(source, true));

ObjectInputStream 读取Obj数据顺序根据写入顺序来,先进先出

在使用对象流写入对象数据时,该对象必须实现Serializable接口
之前接口部分有提到Serializable没有任何方法和常量,它是一个标记类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SMPV6LNC-1613061611899)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211225831552.png)]

下面我们要将两个学生类的信息储存到硬盘中,再通过一个程序将内容读取出来

//学生类,要实现Serializable接口
package IOStudy;import java.io.Serializable;public class Student implements Serializable{/*** */private static final long serialVersionUID = -4870784691100550826L;private String name;private int age;public Student(String name, int age) {super();this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "["+this.getName()+" , "+this.getAge()+"]";}}
//写入信息
package IOStudy;import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;public class ObjectWrite {public static void main(String[] args) throws Exception{String source = "E:\\java程序\\ObjWriter.bin";ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream(source));Student Biden = new Student("Biden", 78);Student Trump = new Student("Trump", 72);obj.writeObject(Trump);obj.writeObject(Biden);obj.writeObject(null);obj.close();System.out.println("Finish");}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3t55wuuK-1613061611900)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212000040489.png)]

//读取信息
package IOStudy;import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;public class ObjectRead {public static void main(String[] args) throws Exception{String source ="E:\\java程序\\ObjWriter.bin";ObjectInputStream obj = new ObjectInputStream(new FileInputStream(source));Object stu;while((stu=obj.readObject())!= null) {System.out.println(stu);}obj.close();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5g4mgD9P-1613061611901)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212000057958.png)]

字符流使用

字符流输入输出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q0B1QXiv-1613061611901)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211225130652.png)]

//实例化对象
FileReader read = new FileReader(Source);
//读取操作与字节流类似//案例(反例),我们使用默认的解码格式读取数据
package IOStudy;import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;public class ReadFile2 {public static void main(String[] args) throws Exception{String Source = "E:\\java程序\\字符Reader.txt";FileReader read = new FileReader(Source);int count =0;while((count = read.read())!= -1) {System.out.print((char)count);}read.close();}
}

结果,中文出现乱码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Mfg0ljR-1613061611903)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211232655649.png)]

由于英文一个字母只占一个字节,默认的GBK解码没有问题。但是中文一个字占3个字节,使用GBK解码(与文本保存的格式不同)出现了乱码。

为了保证能正确解码,我们读取字符文件时要指定解码格式,例如UTF-8

//下面是对上面例子的修改
package IOStudy;import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;public class ReadFile2 {public static void main(String[] args) throws Exception{String Source = "E:\\java程序\\字符Reader.txt";InputStreamReader read = new InputStreamReader(new FileInputStream(Source),"UTF-8");int count =0;while((count = read.read())!= -1) {System.out.print((char)count);}}
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cmLS8dzw-1613061611903)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211233135453.png)]

中文字符流写出时,不用担心上面编码的问题,系统默认是GBK编码,例子如下

package IOStudy;import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;public class WriteFile2 {public static void main(String[] args) throws Exception{String Source = "E:\\java程序\\字符Writer.txt";FileWriter file = new FileWriter(Source);file.write(" 世界你好 ");System.out.println("Finish");file.close();}
}

写入的结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fl8HL4f9-1613061611903)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211233838187.png)]

ANSI就是GBK编码格式

当然,我们也可以指定输出格式,像输入一样

package IOStudy;import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;public class WriteFile2 {public static void main(String[] args) throws Exception{String Source = "E:\\java程序\\字符Writer.txt";OutputStreamWriter file = new OutputStreamWriter(new FileOutputStream(Source,true), "UTF-8");
//      FileWriter file = new FileWriter(Source);file.write(" 世界你好 ");System.out.println("Finish");file.close();}
}

结果:文件使用UTF-8编码格式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yYUtAIF2-1613061611904)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210211234107217.png)]

字符流读取缓冲流
package IOStudy;import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;public class BufferCharRead {public static void main(String[] args) throws Exception{String source = "E:\\编程.txt";BufferedReader buf = new BufferedReader(new InputStreamReader(new FileInputStream(source), "GBK"));for(int i=0;i<20;i++)//打印缓冲区中的前20行//buf.readLine()指读一行数据System.out.println(buf.readLine());buf.close();}
}

文件夹操作

java的IO处理还包括文件夹的一些操作,例如文件夹的创建,删除等

//构造方法
//--1--
File file = new File(String parent_path, String child_path);
//--2--
File file = new File(String absolute_path)
目录操作 解释
createNewFile() 创建一个新文件,不是文件夹
mkdir() 创建一个新目录
delete() 删除文件或空目录
exists() 判断File对象所表示的对象是否存在
getAbsolutePath() 获取文件的绝对路径
getName() 获取目录的名字
getParent() 获取文件/目录所在的目录,
该文件夹所在绝对路径E:\java程序\PicSource\Summer_Pocket
Parent就是E:\java程序\PicSource
Child就是Summer_Pocket
isDirectory() 判断是否是目录
isFile() 判断是否是文件
length() 获取文件的长度,以字节为单位
renameTo() 修改文件名为
listFiles() 列出目录中的所有内容
File[] files = file.listFiles();
返回的是File类型数组
File[] file2 = file.listFiles(FileFilter filter);//可以通过Filefilter进行过滤文件的目的

FileFilter接口


public interface FileFilter
//需要实现的方法
boolean accept(File pathname)

案例

存了一些图片在某个文件夹中,我们要将这些图片重命名,按1-50的顺序重命名

package IOStudy;import java.io.File;
import java.io.FileFilter;
import java.util.Scanner;public class FileOperator {public static void main(String[] args) throws Exception {File file = new File("E:\\java程序\\PicSource");System.out.println("dictory's name: "+file.getName());File[] files = file.listFiles();Integer count =0;for(File pic:files) {File image = new File(file.getAbsolutePath(),count.toString()+".jpg");if(pic.isFile()) {pic.renameTo(image);count++;}}File[] file2 = file.listFiles(new FileFilter() {@Overridepublic boolean accept(File pathname) {if(pathname.getName().endsWith(".jpg"))return true;return false;}});for(File pic:file2) {System.out.println(pic.getName());} }
}

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fqe9AdYz-1613061611905)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212002426056.png)]

Properties

properties是一个属性集合,继承HashTable,是一个线程安全的集合;properties可以储存键值对,同时键值对是字符串类型,它没有泛型。

//构造方法
Properties container = new Properties();//常用方法
container.setProperty("Trump","72");//使用迭代器遍历properties中的键值对
Iterator<Entry<Object, Object>> itr = container.entrySet().iterator();
while(itr.hasNext()) {Entry<Object, Object> set = itr.next();System.out.println(set.getKey()+"=====>"+set.getValue());
}//使用Set遍历键值对
Set<String> set = container.stringPropertyNames();
for(String pro:set) {System.out.println(pro+"=====>"+container.getProperty(pro));
}//load加载存储在硬盘中property的内容
container.load(FileInputStream fis);//以适合的方法将键值对写入到输出流,可以保存注释
container.store(FileOutputStream fos, String comment);
//-----////store方法,以适合的方法将键值对写入到输出流,可以保存注释FileOutputStream fos = new FileOutputStream("E:\\java程序\\properties_save.txt");container.store(fos, "American President");fos.close();
//----////将属性列表输出到指定的输出流
container.list(PrintWriter file);

举一个储存properties的例子

package IOStudy;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;public class PropertyStudy {public static void main(String[] args) throws Exception {Properties container = new Properties();container.setProperty("Trump", "72");container.setProperty("Biden", "74");System.out.println(container.getProperty("Trump"));//使用迭代器遍历Iterator<Entry<Object, Object>> itr = container.entrySet().iterator();while(itr.hasNext()) {Entry<Object, Object> set = itr.next();System.out.println(set.getKey()+"=====>"+set.getValue());}    //将属性列表输出到指定的输出流PrintWriter file =new PrintWriter(new FileOutputStream("E:\\java程序\\properties_save.txt"));container.list(file);file.close();}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qPwJjFAh-1613061611907)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212000516493.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rRe7NZqH-1613061611908)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212000544377.png)]

读取properties在硬盘中的内容

 //load加载properties内容FileInputStream fis = new FileInputStream("E:\\java程序\\properties_save.txt");container.load(fis);fis.close();Set<String> set = container.stringPropertyNames();for(String pro:set) {System.out.println(pro+"=====>"+container.getProperty(pro));}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2oIxvIii-1613061611908)(C:\Users\23881\AppData\Roaming\Typora\typora-user-images\image-20210212000811298.png)]

参考文献

API:https://www.runoob.com/manual/jdk1.6/

菜鸟教程:https://www.runoob.com/java/java-tutorial.html

JAVA final关键字:https://blog.csdn.net/PickUpOldDriver/article/details/80566628

JAVA static block:https://blog.csdn.net/qq_35868412/article/details/89360250

JAVA this关键字:https://blog.csdn.net/qq_43555323/article/details/84993460

JAVA IO:https://blog.csdn.net/baobeiSimple/article/details/1713797

BufferedReader(new InputStreamReader(new FileInputStream(source), “GBK”));
for(int i=0;i<20;i++)//打印缓冲区中的前20行
//buf.readLine()指读一行数据
System.out.println(buf.readLine());
buf.close();
}
}

### 文件夹操作java的IO处理还包括文件夹的一些操作,例如文件夹的创建,删除等```java
//构造方法
//--1--
File file = new File(String parent_path, String child_path);
//--2--
File file = new File(String absolute_path)
目录操作 解释
createNewFile() 创建一个新文件,不是文件夹
mkdir() 创建一个新目录
delete() 删除文件或空目录
exists() 判断File对象所表示的对象是否存在
getAbsolutePath() 获取文件的绝对路径
getName() 获取目录的名字
getParent() 获取文件/目录所在的目录,
该文件夹所在绝对路径E:\java程序\PicSource\Summer_Pocket
Parent就是E:\java程序\PicSource
Child就是Summer_Pocket
isDirectory() 判断是否是目录
isFile() 判断是否是文件
length() 获取文件的长度,以字节为单位
renameTo() 修改文件名为
listFiles() 列出目录中的所有内容
File[] files = file.listFiles();
返回的是File类型数组
File[] file2 = file.listFiles(FileFilter filter);//可以通过Filefilter进行过滤文件的目的

FileFilter接口


public interface FileFilter
//需要实现的方法
boolean accept(File pathname)

案例

存了一些图片在某个文件夹中,我们要将这些图片重命名,按1-50的顺序重命名

package IOStudy;import java.io.File;
import java.io.FileFilter;
import java.util.Scanner;public class FileOperator {public static void main(String[] args) throws Exception {File file = new File("E:\\java程序\\PicSource");System.out.println("dictory's name: "+file.getName());File[] files = file.listFiles();Integer count =0;for(File pic:files) {File image = new File(file.getAbsolutePath(),count.toString()+".jpg");if(pic.isFile()) {pic.renameTo(image);count++;}}File[] file2 = file.listFiles(new FileFilter() {@Overridepublic boolean accept(File pathname) {if(pathname.getName().endsWith(".jpg"))return true;return false;}});for(File pic:file2) {System.out.println(pic.getName());} }
}

结果

[外链图片转存中…(img-fqe9AdYz-1613061611905)]

Properties

properties是一个属性集合,继承HashTable,是一个线程安全的集合;properties可以储存键值对,同时键值对是字符串类型,它没有泛型。

//构造方法
Properties container = new Properties();//常用方法
container.setProperty("Trump","72");//使用迭代器遍历properties中的键值对
Iterator<Entry<Object, Object>> itr = container.entrySet().iterator();
while(itr.hasNext()) {Entry<Object, Object> set = itr.next();System.out.println(set.getKey()+"=====>"+set.getValue());
}//使用Set遍历键值对
Set<String> set = container.stringPropertyNames();
for(String pro:set) {System.out.println(pro+"=====>"+container.getProperty(pro));
}//load加载存储在硬盘中property的内容
container.load(FileInputStream fis);//以适合的方法将键值对写入到输出流,可以保存注释
container.store(FileOutputStream fos, String comment);
//-----////store方法,以适合的方法将键值对写入到输出流,可以保存注释FileOutputStream fos = new FileOutputStream("E:\\java程序\\properties_save.txt");container.store(fos, "American President");fos.close();
//----////将属性列表输出到指定的输出流
container.list(PrintWriter file);

举一个储存properties的例子

package IOStudy;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;public class PropertyStudy {public static void main(String[] args) throws Exception {Properties container = new Properties();container.setProperty("Trump", "72");container.setProperty("Biden", "74");System.out.println(container.getProperty("Trump"));//使用迭代器遍历Iterator<Entry<Object, Object>> itr = container.entrySet().iterator();while(itr.hasNext()) {Entry<Object, Object> set = itr.next();System.out.println(set.getKey()+"=====>"+set.getValue());}    //将属性列表输出到指定的输出流PrintWriter file =new PrintWriter(new FileOutputStream("E:\\java程序\\properties_save.txt"));container.list(file);file.close();}
}

[外链图片转存中…(img-qPwJjFAh-1613061611907)]

[外链图片转存中…(img-rRe7NZqH-1613061611908)]

读取properties在硬盘中的内容

 //load加载properties内容FileInputStream fis = new FileInputStream("E:\\java程序\\properties_save.txt");container.load(fis);fis.close();Set<String> set = container.stringPropertyNames();for(String pro:set) {System.out.println(pro+"=====>"+container.getProperty(pro));}

[外链图片转存中…(img-2oIxvIii-1613061611908)]

参考文献

API:https://www.runoob.com/manual/jdk1.6/

菜鸟教程:https://www.runoob.com/java/java-tutorial.html

JAVA final关键字:https://blog.csdn.net/PickUpOldDriver/article/details/80566628

JAVA static block:https://blog.csdn.net/qq_35868412/article/details/89360250

JAVA this关键字:https://blog.csdn.net/qq_43555323/article/details/84993460

JAVA IO:https://blog.csdn.net/baobeiSimple/article/details/1713797

JAVA入门万字总结相关推荐

  1. 两万字长文总结,梳理 Java 入门进阶那些事

    两万字长文总结,梳理 Java 入门进阶那些事 先给大家看下完整的思维导图,也是这篇文章的主要脉络. Java从入门到进阶学习路线 主导三个项目,让我独当一面 能力提升你要怎么学 全篇总结 Java ...

  2. 两万字长文总结,梳理 Java 入门进阶哪些事(推荐收藏)

    两万字长文总结,梳理 Java 入门进阶哪些事(推荐收藏) 程序员小跃 2021-01-12 13:19:09  23  收藏 分类专栏: Java学习之路 文章标签: java 数据库 redis ...

  3. 两万字梳理 Java 入门进阶那些事

    大家好,我是石头哥,今天跟大家分享一篇 Java 入门到进阶的文章,配合之前我写的[经验分享 -- 程序员编程如何入门.进阶]一起食用更佳哦. 作者是一名在职场已经写了6年程序的老程序员,从一开始的菊 ...

  4. Java入门到架构师知识点整理,P8的技术大咖是这样通关的

    一个人最怕的不是路途遥远,而是看不到胜利曙光.我希望下面这篇文章能给你的学习之路带来一丝曙光,大家不妨试着读一下吧,如果有收获给我点个赞哟. 温馨提醒:这篇文章写着写着就一万字了,建议大家关注后再收藏 ...

  5. Java入门培训班怎么选择

    想要学习java技术,小编一直给小伙伴推荐的是报班学习,目前市面上的java培训机构有很多,对于java培训班的选择很多小伙伴都比较迷茫,下面小编就为大家详细的介绍一下Java入门培训班怎么选择的问题 ...

  6. Java入门学习注意事项有哪些?

    想要学好java技术,做好学习规划路线和注意事项是非常重要的,尤其是零基础学员,Java涉及到的知识点非常多,我们需要制定合理的Java学习路线图,这样会事半功倍,下面小编和大家总结一下Java入门学 ...

  7. Java实用教程笔记 Java入门

    Java入门 JDBC Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新 ...

  8. Java入门(一):Hello World !

    前言 从今天开始,准备写Java Web开发的系列文章,毕竟自己主攻的还是Java方向,Python只是业余学习的兴趣使然,在第二技能还没有培养成熟前,做好第一技能的巩固和提高是很有必要的.从正式入行 ...

  9. 《Java入门经典(第7版)》—— 6.11 练习

    本节书摘来异步社区<Java入门经典(第7版)>一书中的第6章,第6.11节,作者:[美]Rogers Cadenhead(罗格斯 卡登海德),更多章节内容可以访问云栖社区"异步 ...

最新文章

  1. 无招胜有招之Java进阶JVM(八)类加载机制
  2. 用Intel跟AMD CPU烤肉,哪个更香,你们猜猜结果?
  3. 【摘抄】百度分词算法详解:查询处理以及分词技术
  4. java安装版本哪种好_我怎么知道我安装了哪个版本的Java?
  5. Mysql调优你不知道这几点,就太可惜了
  6. 架构师之路:从码农到架构师你差了哪些
  7. 借力阿里云存储产品 延锋彼欧加速数字化重塑
  8. Linux 正则表达式 流编辑之sed awk
  9. 马云:不能把孩子放在温室里,光给孩子知识是不够的
  10. 10.28-11.1-广州软件所-实习工作日记
  11. 什么是Code Review
  12. Google验证码ReCaptcha V3
  13. OpenCV人脸识别
  14. 健康猫涉嫌非法吸收公众存款被立案侦查 9名犯罪嫌疑人被抓
  15. java工程师青春饭吗_Java工程师是青春饭吗?
  16. “你打篮球像蔡徐坤”:微信翻译这个bug是怎么回事?
  17. 产品经理数据分析入门指南
  18. USB 检测外接摄像头
  19. 李嘉诚汕头大学毕业典礼上致辞:无心睡眠
  20. excel数据透视表中插入一列新数据

热门文章

  1. 桌面计算机状态栏在哪,Win7任务栏在哪里 如何调整任务栏位置(图文)
  2. 第四期:如何通过知晓云自动回复客服消息
  3. 图像分类之:经典机器学习 Battle 深度学习
  4. 开学季学生党需要准备哪些数码好物,分享几款实用的数码好物
  5. 机关里看似讨巧实则毁人设的8种行为
  6. 解决显卡驱动错误43
  7. 图片文件,图片文件流和BASE64加密字符串之间的转换,以及图片的BASE64加密字符串再jsp上如何显示
  8. 开源游戏服务器框架汇总
  9. 跑步用挂脖耳机好还是无线耳机、公认最好的跑步耳机推荐
  10. Solr_专题:shema 之 types