一、基础理论篇
1.1 、 计算机的基本概念
(1)万维网的认识
- 万维网:world wide web ,简写www 环球信息网。常简称为web
发明者是蒂姆伯纳斯李。
(2)万维网的分类
- 分为web客户端和web服务器程序。www(万维网)可以让web客户端(常用浏览器)访问器web服务器上面的页面。是一个有许多的相互连接的超文本组成的系统。通过互联网访问在这个系统中每个有用的事物。称为一样的“资源”,并且有一个全局“统一的资源标识符”(URI)标识;这些资源通过超文本传输协议(hyper text transfer protocol)传送给客户,而后者通过点击链接来获取资源。
(3)万维网与互联网、因特网的关系
- 属于包含关系:互联网>因特网>万维网
(4)附:软件和开发程序
软件:是指一系列的按照特定的顺序组织的计算机数据和 指令的集合。由系统软件和应用软件之分 。应用程序=算法+数据结构。
1.2、Windows相关的dos命令
(1)常见dos命令
- DOS命令窗口打开:开始菜单à运行(快捷键:window键+r键)输入“cmd”回车;
-exit :退出当前DOS命令窗口;
-cls :清屏;
-dir :列出当前目录下所有的子文件目录
-cd :change directory改变目录
-md :创建文件夹
-del :删除文件
-rd : 删除文件夹(前提下是保证该文件夹下为空的)
-cd.. :回到上级目录
-cd\ :直接回到根目录
-d:+回车 :切换到d盘
1.3 、java语言的特性及概述
(1)java语言的概述及分类
- Java SE (Java standard edition)标准版:支持面向桌面级应用(如:Windows下的应用程序)的Java平台,提供了完整的Java核心API,此版本以前称为J2SE。
- Java EE(Java enterpride edition)企业版:是为了开发企业环境下的应用程序提供的一套解决方案,该技术体系中包含的技术如:servlet、Jsp等,主要针对于web应用程序开发,版本以前称为J2EE。
- Java ME(Java micro edition)小型版(移动版):支持Java程序运行在移动终端(手机、PDA)上的平台,对Java的API 有所精简,并加入了针对移动终端的支持,此版本以前称为J2ME。
- Java card :支持一些Java小程序(Applets)运行在小内存设备(如智能卡)上的平台。
(2)java的特性
- 简单性:相对而言,例如Java中不再支持多继承,c++是支持多继承的。
- 面向对象
- 可移植性:Java程序可以做到一次编译到处运行。前提是在由Java虚拟机(Java Virtal Machine简称JVM)的情况下。也就是说Java程序可以在Windows系统上运行,不做任何修改,同样Java程序可以直接放到Linux系统上运行。这个被称作为Java的可移植性,或者叫跨平台。但Java程序不能直接和操作系统打交道,需要在Java虚拟机上运行,虚拟机再和底层的操作系统交互。值得一提的是,在哪个操作系统上,Java虚拟机就必须是哪个系统的虚拟机。
- 多线程
- 健壮性
-
1.4 、 java的运行环境搭建
(1)安装jdk(Java development kit Java开发工具包 )
Jdk是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了jre,所以安装了jdk,就不用再单独安装jre了。
- 其中的开发工具:编译工具(Java.exe)、打包工具(jar.exe)等。
- Jre(Java runtime environment Java运行环境)包括了Java虚拟机和Java程序所需的核心类库等。如果想要运行一个开发好的Java程序。计算机中只需要安装jre即可。
- JDK下载地址:www.oracle.com (甲骨文官网)
(2)java的加载与执行
- 环境变量的配置
(3 Java 程序的运行包括两个非常重要的阶段
- 编译阶段:主要任务是检查Java源程序是否符合Java语法,符合Java语法则能够生成正常的字节码文件,反之不能。字节码不是纯粹的二进制代码 ,这种文件无法直接在操作系统中直接执行。
- 编译阶段过程:程序员需要在硬盘的某个位置新建一个Java文件,源文件当中编写的是Java源代码/源程序。再使用jdk中的javac.exe命令进行Java程序的编译。
(4)总结
- 编写java程序的主要的过程:编写—>编译—>运行
- 源文件中可以编译多个类,但最多只能有一个类生成,而且要求声明为public修饰的类名必须于文件名相同。
- 程序的入口是main()方法。格式是固定的:public static void main(String[]args){ }
- 输出语句:System.out.println();
-
1.5、java语言的基本语法
(1)基本语法——关键字与保留字
关键字的分类
- 用于定义数据类型的关键字 :class(类的定义) interface(接口的定义) enum(枚举的定义) byte(字节的定义) short(短整型) int(整型) long(长整型) float(单精度浮点型) double(双精度浮点型) char(字符型) Boolean(布尔型) void(为空)
- 用于定义流程控制的关键字:If else switch case default while do for break continue(跳过该流程) return
- 用于定义类、函数、变量修饰符的关键字:abstract(定义抽象类、方法的关键字) final(最终的) static(静态的) synchronized(同步锁的关键字)
- 用于定义类于类之间的关系的关键字:extends(继承) implements(实现)
- 用于定义建立实例(对象)及引用实例,判断实例的关键字:new(创建对象的关键字) this(表示该对象调用该类的成员变量、成员方法) super(父类的引用) instanceof(判断该类是否为某一类的对象)
- 用于异常处理的关键字:try catch finally throw throws
- 用于包的关键字:Package import
- 其他修饰符的关键字:Native strictfp transient volatile assert
-
java的保留字
现有Java版本尚未使用,单以后版本可能会作为关键字使用的字符串。自己命名标识符要避免使用这些保留字。
- 例如:goto const
(2)基本语法——标识符
定义:Java对各种变量、方法和类等要命名时使用的字符序列称为标识符
- 技巧:凡是自己可以起的名字的地方都叫做标识符。
- 定义合法标识符的规则:
- 由26个英文字母大小写、0-9、_或$组成
- 数字不可以开头。
- 不可以使用关键字和保留字,但能包含关键字和保留字。
- Java中严格区分大小写,长度无限制。
- 标识符不能包含空格。
标识符命名规范
- 包名:多单词组成时所有的字母都为小写
- 类名、接口名:多单词组成时,所有的单词首字母大写
- 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写。
- 常量名:所有字母都大写,多单词时每个单词用下划线连接。
注意:在起名字时,为了提高阅读性,要尽量有意义,做到“见名知意。
(3)基本语法——变量
变量的使用
定义格式:数据类型 变量名=变量值;
说明:变量必须先声明,后使用;变量都定义在其作用域内,在作用域内,它时有效的,同一个作用域内,不可以声明同名的变量。
变量的分类
基本数据类型:
- 整型:byte short int long
- 整型之间的换算关系:1byte(字节)=8bit(位)、1short=2byte、1int=4byte Long = 8byte
- 组合数(取值范围):byte:2的8次方(-128~127);short:2的16次方;Int:2的32次方;long:2的64次方。
- 注意:声明long型变量,必须以“l”或“L”结尾,通常定义整形变量时使用int型。
- 浮点型:float double
- 换算关系:1float=4byte、1double=8byte
- 组合数:值得注意的是,float表示的取值返回比long的取值范围还大,因为float的存储数据的方式不同。
- 注意:定义float变量时,变量要以“f”或“F”结尾。通常定义浮点型变量是使用double类型的。
- 字符型:char
- 换算关系:1char=2byte
- 格式:通常定义char类型的变量时使用一对单引号将变量值包裹起来,且变量值只能写一个字符。
- 布尔类型:boolean
- 取值:false 、 true
- 使用场景:用于条件判断、循环流程体系
引用数据类型
自动类型的提升
- 理解:当容量小的数据类型的变量与容量大的数据类型的变量做运算时,结果自动提升位容量大的数据类型。
- 规则:Byte、char、short->int ->long-> float-> double
- 强制类型转换
- 理解:取值范围小的接收取值范围大
- 格式 :需要使用强转符:()
String类型变量的使用
运算符的概览:运算符有:“+、-、*、/、%(取余或取模)、++”
- 取余运算:取余的结果为余数,结果的符号与被模数的符号相同。
- ++运算:前++:先自增,后运算;后++:先运算,后自增。
- 赋值运算:+=、-=、*=、/=。表示自身与其他值或变量相加/减/乘/除,再赋值给自己
- 逻辑运算
- &、&&:与运算,遇false则false
- |、||:或运算,遇true则true
- !:非运算,取反
- ^:异非运算,相同为false,反之则反
- &或&&的相同点:输出结果相同,二者当符号左边的是true时,二者都会执行符号右边的运算。其不同点:当符号左边的时false时,&&不会执行符号右边的运算。
位运算
- 说明:位运算符操作的都是整型数据类型。
- 运算符: i<<1(左移一位):相当于2;反之则反 ; 公式:i << n ; 相当于i * 2 的n次幂
进制之间的转换
- 计算机处理数据的方式是以二进制来处理的,这里涉及到几个知识点:源码、反码和补码
- 正数的源码反码补码是其二进制的本身
- 负数的反码是源码按位取反,补码是在反码的基础上加一,在计算机底层负数是以补码的方式进行运算处理的 ```java //练习:将60转换为十六进制。
class ConsTest{
public static void main(String[]args){
int i1 = 60; //定义一个int型变量。60的二进制是00111100
int i2 = i1&15; /*变量i1和常量15按位与运算,因为15的二进制是1111。
结果为1100,其十进制为12。(目的是为了取出其二进制的后四位)*/
String j =(i2>9)?(char)(i2-10+'A')+"":i2+""; /*i2为12,i2>9为true,
则执行i2-10+‘A’的表达式。结果为C。*/
int temp =i1>>>4; //变量i1进行无符号右移4位,结果为0011,其十进制为3(取出前四位)
i2 = temp;//i2 = temp&15;
String k =(i2>9)?(char)(i2-10+'A')+"":i2+"";
System.out.println(k+""+j);
}
} //最后输出结果为:3C
- 三元运算符
- 结构:(条件表达式)?表达式1:表达式2;
- 说明:条件表达式的结果为boolean类型;根据条件表达式的真假值,决定执行表达式1还是表达式2;如果条件表达式为true ,则执行表达式1;反之则反。表达式1和表达式2要求一致(及定义的类型可以统一)
- 额外说明:三元运算符可以嵌套使用。凡是可以使用三元运算符的地方。都可以改写成if-else。反之则反。如果程序既可以使用三元运算符,又可以使用if-else结构,那么优先选择三元运算符。
<a name="759a378c9f076d7ebff2ab108ebfd360"></a>
#### 流程控制
- 分类
- 顺序结构
- 分支结构
<a name="442c487f4a63ac268047d7ed93e0d7e4"></a>
#### Switch- case结构
- 格式:
```java
switch(表达式){
case 常量1:
执行语句1;
break;
case 常量2:
执行语句2;
break;
......
default:
执行语句n;
break;
}
- 说明:根据switch表达式中的值,依次匹配各个case中的常量。匹配成功,则进入相应的case结构中,调用其执行语句,当调用完执行语句后,则仍然继续向下执行其他的case结构中的执行语句。直到遇到break关键字或此switch-case结构末尾为止结束。switch结构中的表达式,只能是如下的6种数据类型之一:Byte、short、char、int、枚举类型(jdk5新增)、String类型(jdk7新增)。case之后只能声明常量,不能声明范围。从开发的角度来说明:凡是可以使用switch-case的结构,都可以转换成if-else。反之不成立我们写分支结构是,当发现既可以用switch-case(switch中的表达式的取值情况不太多),又可以使用if-else时,我们优先选择使用switch-case。原因:switch-case执行效率稍高。
- 案例: ```java /* switch语句练习1 从键盘分别输入年、月、日,判断这一天时当年的第几天
*/
import java.util.Scanner; class SwitchcaseExwe1{
public static void main(String[]args){
System.out.println("请输入年份。");
Scanner scan = new Scanner(System.in);
int yeah = scan.nextInt();
System.out.println("请输入月份。");
Scanner scan1 = new Scanner(System.in);
int month = scan.nextInt();
System.out.println("请输入日期。");
Scanner scan2 = new Scanner(System.in);
int days = scan.nextInt();
//定义一个总的天数变量。
int sumdays = 0;
switch (month){
case 12:
sumdays += 30;
case 11:
sumdays += 31;
case 10:
sumdays += 30;
case 9:
sumdays += 31;
case 8:
sumdays += 31;
case 7:
sumdays += 30;
case 6:
sumdays += 31;
case 5:
sumdays += 30;
case 4:
sumdays += 31;
case 3:
if((yeah%4 == 0&&yeah%100 != 0)||yeah%400 == 0){
System.out.println(sumdays += 29);
}else{
System.out.println(sumdays += 28);
}
case 2:
sumdays += 31;
case 1:
sumdays += days;
System.out.println(sumdays);
}
}
}
```java
/*switch语句练习1
编写一个程序,为一个给定的年份找出其相对应的中国生肖。中国的生肖基于12年一个周期
每年用一个动物代表:rat、ox、tiger、rabbit、dragon、snake、horse、sheep、monkey、rooster
dog、pig。
*/
import java.util.Scanner;
class SwitchcaseExer{
public static void main(String[]args){
Scanner scan = new Scanner(System.in);
System.out.println("请输入年份");
int yeah = scan.nextInt();
//System.out.println("yeah");
switch (yeah%12){
case 1:
System.out.println("该年份为鸡年");
break;
case 2:
System.out.println("该年份为狗年");
break;
case 3:
System.out.println("该年份为猪年");
break;
case 4:
System.out.println("该年份为鼠年");
break;
case 5:
System.out.println("该年份为牛年");
break;
case 6:
System.out.println("该年份为虎年");
break;
case 7:
System.out.println("该年份为兔年");
break;
case 8:
System.out.println("该年份为龙年");
break;
case 9:
System.out.println("该年份为蛇年");
break;
case 10:
System.out.println("该年份为马年");
break;
case 11:
System.out.println("该年份为羊年");
break;
case 0:
System.out.println("该年份为猴年");
break;
//System.out.println("")
}
}
}
随机数的获取
- 通过Math类中的静态方法random方法获取
//想要获取[a,b]区间的随机数
int random = (int)(Math.random()*(b - a + 1) + a)
循环结构
循环结构四要素
结构:
for(初始条件;循环条件;迭代条件){
循环体;
}
案例:
/**
for循环案例之菱形
*/
class Lingxing{
public static void main(String[]args){
//上半部分
for(int i = 1;i < 5;i++){
for(int j = 1;j < 6 - i;j++ ){
System.out.print(" ");
}
for(int l = 1;l <= 1 +(i - 1) * 2;l++ ){
System.out.print("*");
}
System.out.println();//内循环执行完一次换行的程序
}
//下半部分
for(int i = 1;i < 4;i++){
for(int j = 1;j <= i + 1;j++){ //这里之所以要加一,是因为下半部分要缩进一格
System.out.print(" ");
}
for(int l = 1;l < 8 - 2*i;l++){
System.out.print("*");
}
System.out.println();//同上
}
}
}
```java / 输入所有的水仙花数,所谓水仙花数 是指一个三位数,其各个位上的数字 立方和等于其本身。 /
class ForExer1{
public static void main(String[]args){
int count = 0;
for (int i = 100;i<1000;i++){
int bai = i/100;
int shi = i%100/10;
int ge = i%10;
if (i == (bai*bai*bai+shi*shi*shi+ge*ge*ge)){
System.out.print(i+" ");
count++;
if(count % 2 == 0){
System.out.println();
}
}
}
System.out.println("水仙花数的个数为:"+count);
}
}
```java
/*
输入两个正整数m和n,求其最大公约数和最小公倍数。
*/
import java.util.Scanner;
class ForExer{
public static void main(String[]args){
Scanner scan = new Scanner(System.in);
System.out.println("输入一个正整数。");
int number1 = scan.nextInt();
//Scanner scan = new Scanner(System.in);
System.out.println("输入第二个正整数。");
int number2 = scan.nextInt();
System.out.println();
//最大公约数求值
int max= (number1>=number2)?number1:number2;
for(int i=max;i>=1;i--){
if(number1%i == 0&&number2%i ==0){
System.out.println(i);
break;
}
}
int min = (number1<=number2)?number1:number2;
for(int i = min;i<=number1*number2;i++){
if(i%number1 ==0&&i%number2 == 0){
System.out.println(i);
break;
}
}
}
}
/*
1.分析以下需求,并用代码实现:
(1)按照从大到小的顺序输出四位数中的个位+百位=十位+千位(3553,2332,1166,8228,3773)的数字及个数
(2)每行输出5个满足条件的数,之间用空格分隔
(3)如:9999 9988 9977 9966 9955
*/
class work1{
public static void main(String[] args) {
//for循环实现
int count = 0;
for (int i = 9999; i >= 1000; i--) {
int ge = i % 10;
int bai = i / 10 / 10 % 10;
int shi = i / 10 % 10;
int qian = i / 1000;
if (ge + bai == shi + qian) {
count++;
System.out.print(i + " ");
if (count % 5 == 0) {
System.out.println();
}
}
}
System.out.println("满足条件的数有"+count+"个");
}
}
/*
3.分析以下需求,并用代码实现:
(1)打印1到100之内的整数,但数字中包含9的要跳过
(2)每行输出5个满足条件的数,之间用空格分隔
(3)如:1 2 3 4 5
*/
class work3{
public static void main(String[]args){
int count = 0;
for(int i = 1;i <= 100;i++){
if(i/10==9||i==9||i%10==9){
continue;
}
count++;
System.out.print(i+" ");
//count++; 计数器只要不写在if里面顺序就不受影响
if(count%5==0){
System.out.println();
}
}
}
}
4.分析以下需求,并用代码实现:
(1)打印1-100之间的所有素数及个数
(2)每行输出5个满足条件的数,之间用空格分隔
(3)如果一个大于1的自然数,这个数只能被1和其本身整除,这个数就叫素数
*/
class work4{
public static void main(String[]args){
int count = 0;
boolean b = true;//标识i是否被j除尽,一旦除尽就修改其值
for(int i=2;i<=100;i++){//遍历100以内的自然数
for(int j=2;j<i;j++){//让每个i除以j
if(i%j==0){
b=false;//i被j除尽就重新赋值标记
break;
}
}
if(b==true){//看看变量b是否还是原来的值,是就说明该i没有被j除尽是素数,输出打印
count++;
System.out.print(i+" ");
if(count%5==0){
System.out.println();
}
}
b=true;//注意,标记变量b要重新定义,写在外层循环内当外层循环体。
}
System.out.println("素数的个数为"+count);
}
}
6.倒着打印九九乘法表
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
......
*/
class work6{
public static void main(String[]args){
//for循环实现
for(int i=1;i<=9;i++){
for(int j=1;j<=10-i;j++){
System.out.print(j+"*"+(10-i)+"="+((10-i)*j)+" ");
}
System.out.println();
}
//数组实现
int mul[][]=new int[9][];
//赋值
for(int i=0;i<mul.length;i++){
mul[i]=new int[9-i];
for(int j=0;j<mul[i].length;j++){
mul[i][j]=(9-i)*(j+1);
}
}
//数组遍历
for(int i=0;i<mul.length;i++){
for(int j=0;j<mul[i].length;j++){
System.out.print((j+1)+"*"+(9-i)+"="+mul[i][j]+" ");
}
System.out.println();
}
}
}
while循环
结构:
初始化条件
while(循环条件){
循环体;
迭代条件;
}
案例 ```java / 2.分析以下需求,并用代码实现: (1)珠穆朗玛峰高度为8848米,有一张足够大的纸,厚度为0.001米。 (2)请问,我折叠多少次,可以折成珠穆朗玛峰的高度。 /
class work2{ public static void main(String[]args){ int count = 0; int zf = 8848; double paper = 0.001; while(paper<=zf){ paper *= 2; count++; System.out.println(paper); } System.out.println(count); } }
public static void main(String [] args){ //编写程序,使用while循环语句计算1 + 1/2!+ …… +1/20 ! 之和 double i = 1; double j = 1; double ji = 1; double sum = 0; while(i <= 20){ while(j <= i){ ji *= 1 / j; j++; } sum +=ji; i++; } System.out.println(sum); }
<a name="0e47e685ecca36e60e59b092bb5ea3d8"></a>
#### do-while循环
- 结构
```java
do{
循环体;
迭代条件;
}while(循环条件);
- 说明:do-while至少执行一次循环体。
开发经验总结说明:这三种循环的使用次数。For和while使用的次数多些。
死循环
for(;;)或while(true);一般用后者,结束循环的两种方法:循环条件为false;在循环体中执行break
嵌套循环使用技巧:
内层循环结构遍历一次,只相当于外层循环循环体执行了一次,假设外层循环需要执行了m次,内层循环需要执行n次,此时内层循环体一共执行了m*n次。小技巧:外层循环控制行数,内层循环控制列数。
break和continue关键字的使用
| 关键字名称 | 使用范围 | 循环中使用的作用(不同点) | 相同点 | | —- | —- | —- | —- | | break | switch-case、
循环结构中 | 结束当前循环(后面不执行) | 结束当次循环(后面继续执行) | | continue | 循环结构中 | 结束当次循环(后面继续执行) | |
终:衡量一个功能代码的优劣性
- 正确性
- 可读性
- 健壮性
- 高效性和低存储:时间复杂度、空间复杂度
二、数组、方法、对象
2.1、数组
(1)数组的认识
- 理解:数组(Array),是多个相同类型数据按一定的排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
- 数组的相关名词概念
- 数组名
- 元素
- 角标、下标、索引
- 数组的长度(元素的个数)
- 数组的特点:
- 数组是有序排列的
- 数组属于引用数据类型的变量。但数组的元素,既可以是基本数据类型也可以是引用数据类型。
- 创建数组对象会在内存中开辟一整块连续的空间。
- 数组的长度一旦确定,就不能修改。
数组的分类
掌握的要点
- 一维数组的声明与初始化
- 如何调用数组的指定位置的元素
- 如何获取数组的长度
- 如何遍历数组的元素
- 数组元素的默认初始化值
- 数组的内存解析
一维数组的声明与定义格式
public class ArrayTest{
public static void main(String[]args){
int[] ids; //声明
//静态初始化:数组的初始化和数组元素的赋值操作同时进行
ids = new int[]{1001,1002,1003,1004};
//动态初始化:数组的初始化和数组元素的赋值操作分开进行
String[] names = new String[5];
}
}
数组的声明与定义的总结:数组一旦初始化完成,其长度就确定了
- 数组元素的默认初始化值
- 数组元素是整型:0
- 数组元素是浮点型:0.0
- 数组元素是char型:0或’\u0000’,而非’0’
- 数组元素是boolean型:false
- 数组元素是引用类型:null
- 课外问题:int[]x,y[]:他代表的是一个为int[]x的一维数组和一个为int[][]y的二维数组
数组案例:
package com.lee.arr2;
/*
二维数组的定义、
*/
public class doublearr {
public static void main(String[] args) {
//二维数组定义
int arr [][] = {{2,3,4},{5,6,7}};
int arr1 [][] = new int [3][];
//赋值
//遍历数组元素
for (int i = 0 ; i < arr.length;i++){
for (int j = 0; j <arr[i].length; j++){
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
System.out.println();
System.out.println(arr[1]);//地址值
System.out.println();
System.out.println(arr1);//地址值
System.out.println();
System.out.println(arr[1][0]);// 5
System.out.println();
System.out.println(arr1[1][0]);//Process finished with exit code 1
}
}
```java /* 求数值型数组中元素的最大值、最小值、平均值、总和等。
例题:定义一个int型的一维数组,包含10个元素,分别赋 一些随机整数,然后求出所有元素的最大值,最小值,和值, 平均值,并输出出来。(要求:所有元素都是两位数)
*/
class arrys{ public static void main(String[]args){ int []arrys = new int[10]; //首先声明、初始化一个int型数组 int sumArry = 0; int i = 0; while(i < arrys.length){ arrys[i] = (int)(Math.random()(99-10+1)+10); //随机取值 //[10,99]:(int)(Math.random()) i++; } //遍历 for(int l = 0;l < arrys.length;l++){ System.out.println(arrys[l]); sumArry += arrys[l]; } System.out.println(“和值为:”+sumArry); //求最大值 int maxArry = arrys[0]; int j = 1; while(j < arrys.length){ if(maxArry < arrys[j]){ maxArry = arrys[j]; } j++; } System.out.println(“最大值为:”+maxArry); //求最小值 int minArry = arrys[0]; int k = 0; while(k < arrys.length){ if(minArry > arrys[k]){ minArry = arrys[k]; } k++; } System.out.println(“最小值为:”+minArry); }
}
```java
package com.lee.arr2;
/*
使用二维数组打印一个10行杨辉三角。
*/
public class doublearr1 {
public static void main(String[] args) {
//定义一个外层元素长度为10的二维数组
int yanghui[][] = new int[10][];
//赋值
for (int i = 0; i < yanghui.length; i++){
//因为二维数组的外层元素是个一维数组,因此要new一个
yanghui[i] = new int[i + 1];
//给首尾的元素赋值
yanghui[i][0] = yanghui[i][i] = 1;
//给非首尾的元素赋值
if (i > 1){
for (int j = 1;j < yanghui[i].length - 1;j++){
yanghui[i][j]=yanghui[i-1][j-1]+yanghui[i-1][j];
}
}
}
//遍历数组
for (int i = 0;i < yanghui.length;i++){
for (int j = 0;j < yanghui[i].length;j++){
System.out.print(yanghui[i][j] + " ");
}
System.out.println();
}
}
//冒泡排序
int arr [] = {45,34,5,23,55,66,76,1,100,3,99};
for (int i = 0; i < arr.length-1; i++) {//排序两个响铃的元素进行比较,只要比较数组长度减一次就行
for (int j = 0; j < arr.length-1-i; j++) {
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
package com.xiaoha.day04;
/**
* 数组的二分查找法
*
* @author HausenLee
* @date 2021/04/25
*/
public class ALGArrEX02 {
public static void main(String[] args) {
//说明:使用二分法查找指定的元素,前提要保证
//数组的元素是有序的(不管是从大到小还是从小到大
//只要是有序的就行)
int [] arr = {4,6,8,10,13,15,66,78,93,100,120};
//定义一个要查找的变量
int dest = 66;
//定义一个开始索引
int start = 0;
//定义一个尾索引
int end = arr.length - 1;
boolean flog = true;
while(start <= end){ //循环条件开始索引不能超过尾索引
//计算出中间索引
int middle = (start + end) / 2;
if(dest == arr[middle]){ //如果目标数值等于了中间索引对应的元素,就说明找到了
System.out.println("找到了指定的元素,位置在:"+ middle);
flog = false;
break;
}else if(dest < arr[middle]){
end = middle - 1;
}else{
start = middle + 1;
}
}
if(flog){
System.out.println("抱歉,没找到指定的元素");
}
}
}
- 数组反转 ```c package com.xiaoha.day04;
/**
- 数组的反转操作 *
- @author HausenLee
- @date 2021/04/25
*/
public class ALGArrEX01 {
public static void main(String[] args) {
} } ```String [] arr = new String []{"AA","DD","TD","MD","HH","WW","ss"};
for (int i = 0; i <= arr.length / 2; i++) { //可以是大于,也可以是大于等于
String temp = arr[i];
arr[i] = arr[arr.length - i -1];
arr[arr.length - i -1] = temp;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] +" ");
}
2.2、面向对象(继承)
(1)继承的认识
- 继承的概念
- 继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法
- 实现继承的格式
- 继承通过extends实现
- 格式:class 子类 extends 父类 { } ```java /**
- 举例 */ class Dog extends Animal { } ```
- 继承带来的好处
- 继承可以让类与类之间产生关系,子父类关系,产生子父类后,子类则可以使用父类中非私有的成员。
- 注:private修饰的成员变量或成员方法依然可以被继承,只不过是因封装性的原因被隐藏了。
示例代码
public class Fu {
public void show() {
System.out.println("show方法被调用");
}
}
public class Zi extends Fu {
public void method() {
System.out.println("method方法被调用");
}
}
public class Demo {
public static void main(String[] args) {
//创建对象,调用方法
Fu f = new Fu();
f.show();
Zi z = new Zi();
z.method();
z.show();
}
}
(2)继承的好处与弊端
继承的好处
- 提高了代码的复用性(多个类相同的成员可以放到同一个类中)
- 提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
- 继承的弊端
- 继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时子类实现也不得不跟着变化,削弱了子类的独立性
继承的应用场景
继承中变量的访问特点
- 在子类方法中访问一个变量,采用的是就近原则。
- 子类局部范围找
- 子类成员范围找
- 父类成员范围找
- 如果都没有就报错(不考虑父亲的父亲…)
- 示例代码
class Fu {
int num = 10;
}
class Zi extends fu {
int num = 20;
public void show(){
int num = 30;
System.out.println(num);
}
}
public class Demo1 {
public static void main(String[] args) {
Zi z = new Zi();
z.show(); // 输出show方法中的局部变量30
}
}
(4)supper关键字
- 在子类方法中访问一个变量,采用的是就近原则。
this&super关键字:
- this:代表本类对象的引用(区分成员变量)
- super:代表父类存储空间的标识(可以理解为父类对象引用)
this和super的使用分别
注意:子类中所有的构造方法默认都会访问父类中无参的构造方法
- 子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,原因在于,每一个子类构造方法的第一条语句默认都是:super()
问题:如果父类中没有无参构造方法,只有带参构造方法,该怎么办呢
通过子类对象访问一个方法
对象在堆内存中,会单独存在一块super区域,用来存放父类的数据
(8)方法的重写
方法重写概念
- 子类出现了和父类中一模一样的方法声明(方法名一样,参数列表也必须一样)
- 方法重写的应用场景
- 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容
- Override注解
- 用来检测当前的方法,是否是重写的方法,起到【校验】的作用
方法重写的注意事项
- 私有方法不能被重写
- 父类被重写的方法返回值是void,则子类重写的方法返回值只能是void
- 父类被重写的方法返回值是A类型的,则子类重写的方法返回值可以是A类型或A类型的子类型
- 父类被重写的方法返回值是基本类型的(比如double),则子类重写的方法返回值必须是相同的(double)
- 子类重写的方法抛出的异常类型小于等于父类被重写方法抛出的异常类型,
- 子类方法访问权限要大于等于父类的方法访问权限(public > 默认 > 私有)
示例代码 ```java public class Fu { private void show() { System.out.println(“Fu中show()方法被调用”); }
void method() { System.out.println(“Fu中method()方法被调用”); } }
public class Zi extends Fu {
/* 编译【出错】,子类不能重写父类私有的方法*/
@Override
private void show() {
System.out.println("Zi中show()方法被调用");
}
/* 编译【出错】,子类重写父类方法的时候,访问权限需要大于等于父类 */
@Override
private void method() {
System.out.println("Zi中method()方法被调用");
}
/* 编译【通过】,子类重写父类方法的时候,访问权限需要大于等于父类 */
@Override
public void method() {
System.out.println("Zi中method()方法被调用");
}
}
<a name="9ce423baedf287fc0bdf93622fdb80a1"></a>
### (9)java中继承的注意事项
- Java中类只支持单继承,不支持多继承。错误范例:class A extends B, C { }
- Java中类支持多层继承。示例代码
```java
public class Granddad {
public void drink() {
System.out.println("爷爷爱喝酒");
}
}
public class Father extends Granddad {
public void smoke() {
System.out.println("爸爸爱抽烟");
}
}
public class Mother {
public void dance() {
System.out.println("妈妈爱跳舞");
}
}
public class Son extends Father {
// 此时,Son类中就同时拥有drink方法以及smoke方法
}
2.3继承练习
(1)案例题目:老师和学生
- 需求:定义老师类和学生类,然后写代码测试;最后找到老师类和学生类当中的共性内容,抽取出一个父类,用继承的方式改写代码,并进行测试
- 步骤:
- 定义老师类(姓名,年龄,教书())
- 定义学生类(姓名,年龄,学习())
- 定义测试类,写代码测试
- 共性抽取父类,定义人类(姓名,年龄)
- 定义老师类,继承人类,并给出自己特有方法:教书()
- 定义学生类,继承人类,并给出自己特有方法:学习()
- 定义测试类,写代码测试
示例代码 ```java class Person { private String name; private int age;
public Person() { }
public Person(String name, int age) {
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;
} }
class Teacher extends Person {
public Teacher() {}
public Teacher(String name,int age) {
super(name,age);
}
public void teach() {
System.out.println("用爱成就每一位学员");
}
}
class Student extends Person{ public Student() {}
public Student(String name, int age) {
super(name,age);
}
public void study(){
System.out.println("学生学习");
}
}
class PersonDemo { public static void main(String[] args){ //创建老师类对象并进行测试 Teacher t1 = new Teacher(); t1.setName(“林青霞”); t1.setAge(30); System.out.println(t1.getName() + “,” + t1.getAge()); t1.teach();
Teacher t2 = new Teacher("风清扬", 33);
System.out.println(t2.getName() + "," + t2.getAge());
t2.teach();
// 创建学生类对象测试
Student s = new Student("张三",23);
System.out.println(s.getName() + "," + s.getAge());
s.study();
}
}
<a name="3c8574abaa28bec9742a26896a82af92"></a>
### (2)案例题目:猫和狗
- 需求:请采用继承的思想实现猫和狗的案例,并在测试类中进行测试
- 分析步骤:
- 猫:
- 成员变量:姓名,年龄
- 构造方法:无参,带参
- 成员方法:get/set方法,抓老鼠()
- 狗:
- 成员变量:姓名,年龄
- 构造方法:无参,带参
- 成员方法:get/set方法,看门()
- 它们之间的共性:
- 成员变量:姓名,年龄;构造方法:无参,带参;成员方法:get/set方法
首先定义动物类:【成员变量:姓名、年龄】【构造方法:无惨,有参】【成员方法:get/set方法】<br />再者定义cat类:继承动物类:【构造方法:无参、有参】成员方法【抓老鼠()】<br />再者定义dog类:继承动物类:【构造方法:无参,有参】成员方法【看门()】<br />最后定义测试类:测试
- 示例代码:
```java
class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
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;
}
}
class Cat extends Animal {
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
public void catchMouse() {
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal {
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
public void lookDoor() {
System.out.println("狗看门");
}
}
/*
测试类
*/
public class AnimalDemo {
public static void main(String[] args) {
//创建猫类对象并进行测试
Cat c1 = new Cat();
c1.setName("加菲猫");
c1.setAge(5);
System.out.println(c1.getName() + "," + c1.getAge());
c1.catchMouse();
Cat c2 = new Cat("加菲猫", 5);
System.out.println(c2.getName() + "," + c2.getAge());
c2.catchMouse();
}
}
2.4 、修饰符
(1)修饰符package
- 包概念:包就是文件夹,用来管理类文件的
- 包的定义格式
- package 包名;(多级包用.隔开)
- 例如:package com.xiaoha.Demo
带包编译&带包运行
导包的意义:使用不同包下的类时,使用时要写类的全路径,写起来太麻烦,为了简化带包的操作,java就提供了导包的功能。
- 导包的格式:inport 包名;
- 导包的范例:inport java.util.Scanner;
- 示例代码(没有使用导包,创建Scanner对象): ```java package com.heima;
public class Demo { public static void main(String[] args) { // 1. 没有导包,创建Scnaner对象 java.util.Scanner sc = new java.util.Scanner(System.in); } }
- 示例代码(使用导包创建Scanner对象)
```java
package com.heima;
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
// 1. 使用导包,创建Scnaner对象
Scanner sc = new Scanner(System.in);
}
}
(3)权限修饰符
(4)修饰符final
- final修饰基本数据类型局部变量或成员变量时,变量的值不能再次发生改变,相当于一个常量了。
final修饰引用类型的变量时,引用数据类型的地址值不能发生改变(不能再次创建该类的对象),但是地址里面 的内容是可以发送改变的。例如:
public static void main(String[] args){
final Student s = new Student(23);
s = new Student(24); // 错误
s.setAge(24); // 正确
}
(5)修饰符static
static的概念:static是静态的意思,可以修饰成员方法,成员变量
- static修饰的特点:被类的所有对象进行共享,我们创建多个对象,多个对象共享同一个静态变量,当通过某个对象修改了静态变量时,会导致其他对象调用此变量时,是修改过的。这也是我们判断是否使用静态关键字的条件。可以通过类名调用,当然也可以通过对象名调用(推荐使用类名调用)。静态变量的加载要早于对象的创建。由于类值加载一次,则静态变量在内存中也只会存在一份,存在方法区的静态域中。静态方法不能访问对象中的属性,因为它不能操作对象。但是静态方法可以访问自身类中的静态属性。
示例代码 ```java class Student {
public String name; //姓名 public int age; //年龄 public static String university; //学校 共享数据!所以设计为静态!
public void show() {
System.out.println(name + "," + age + "," + university);
}
}
public class StaticDemo { public static void main(String[] args) { // 为对象的共享数据赋值 Student.university = “传智大学”;
Student s1 = new Student();
s1.name = "林青霞";
s1.age = 30;
s1.show();
Student s2 = new Student();
s2.name = "风清扬";
s2.age = 33;
s2.show();
}
}
<a name="10a488f490e2fa52e3dc09767806418d"></a>
### (6)被static修饰的方法访问其他类或成员变量、成员方法的特点
- 特点:
- 非静态的成员方法
- 能访问静态的成员变量
- 能访问非静态的成员变量
- 能访问静态的成员方法
- 能访问非静态的成员方法
- 静态的成员方法
- 能访问静态的成员变量
- 能访问静态的成员方法
- 总结一句话就是:静态的成员方法只能访问静态成员
<a name="jgwVK"></a>
### (7)static注意点
- 在静态方法 内,不能使用this关键字、super关键字
<a name="f57e491fb546c08b02a38bb11902be77"></a>
# 三、多态
<a name="9a790beb59972121e2ea8f09dabd74b8"></a>
## 3.1、多态的认识
(1)多态的概念
- 概念:同一个对象在不同时刻表现出来的不同的形态
- 多态的前提
- 要有继承或实现关系
- 要有方法的重写
- 要有父类引向子类对象
(2)多态中的成员访问特点
- 成员变量:编译看父类,运行看父类
- 成员方法:编译看父类,运行看子类(因为有方法的重写)
- 示例代码:
- 动物类
```java
public class Animal {
public int age = 40;
public void eat() {
System.out.println("动物吃东西");
}
}
猫类
public class Cat extends Animal {
public int age = 20;
public int weight = 10;
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void playGame() {
System.out.println("猫捉迷藏");
}
}
测试类
public class AnimalDemo {
public static void main(String[] args) {
//有父类引用指向子类对象
Animal a = new Cat();
System.out.println(a.age);
// System.out.println(a.weight);
a.eat();
// a.playGame();
}
}
3.2、多态的优点与弊端
(1)优点:提高程序的扩展性。定义方法时候,使用父类型作为参数,在使用的时候,使用具体的子类型参与操作
(2)弊端:不能使用子类的特有成员
3.3、多态中的转型以及instanceof关键字的使用
(1)分类
- 向上转型
- 父类引用指向子类对象就是向上转型
向下转型(使用向下转型的时候为了避免出现类型转换的异常,使用instanceof进行判断)
- a instanceof A :判断对象a是否是类A的实例,如果是,返回true,反之则反。
- 格式: 子类型 对象名 = (子类型)父类引用
代码示例
动物类
public class Animal {
public void eat() {
System.out.println("动物吃东西");
}
}
猫类 ```java public class Cat extends Animal { @Override public void eat() { System.out.println(“猫吃鱼”); }
public void playGame() { System.out.println(“猫捉迷藏”); } } ```
- 测试类 ```java public class AnimalDemo { public static void main(String[] args) { //多态 //向上转型 Animal a = new Cat(); a.eat(); // a.playGame();
//向下转型
Cat c = (Cat)a;
c.eat();
c.playGame();
}
}
<a name="48909b22417f173f2c44f355ad7c929e"></a>
## 3.4、多态的案例
(1)案例需求
- 请采用多态的思想实现猫和狗的案例,并在测试类中进行测试
- 代码实现
- 动物类
```java
public class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
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;
}
public void eat() {
System.out.println("动物吃东西");
}
}
- 猫类
public class Cat extends Animal {
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
- 狗类
public class Dog extends Animal {
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
- 测试类
public class AnimalDemo {
public static void main(String[] args) {
//创建猫类对象进行测试
Animal a = new Cat();
a.setName("加菲");
a.setAge(5);
System.out.println(a.getName() + "," + a.getAge());
a.eat();
a = new Cat("加菲", 5);
System.out.println(a.getName() + "," + a.getAge());
a.eat();
}
}
3.5、抽象类
(1)抽象类的认识
- 抽象类的概述
- 当我们在子类做共性代码功能抽取时,有些方法在父类中并没有具体的体现,这个时候就需要抽象类了!在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类!
- 抽象类的特点
- 抽象类和抽象方法必须使用关键字abstract修饰 ```java //抽象类的定义 public abstract class 类名 {}
//抽象方法的定义 public abstract void eat();
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 抽象类不能实例化,抽象类如何实例化呢?参照多态的方式,通过子类对象实例化,这叫抽象类多态
- 抽象类的子类,要么重写抽象类中的所有抽象方法;要么是抽象类
- 抽象类成员的特点
- 成员特点:
- 成员变量:既可以是变量;也可以是常量
- 成员方法:抽象方法,普通方法,但必须要有抽象方法
- 构造方法:空参构造方法,有参构造方法
- 代码示例
- 动物类
```java
public abstract class Animal {
//变量
private int age = 20;
//常量
private final String CITY = "北京";
//空参构造方法
public Animal() {}
//有参构造方法
public Animal(int age) {
this.age = age;
}
//普通成员方法
public void show() {
age = 40;
System.out.println(age);
// city = "上海";
System.out.println(city);
}
//抽象犯法
public abstract void eat();
}
猫类
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
测试类
public class AnimalDemo {
public static void main(String[] args) {
Animal a = new Cat();
a.eat();
a.show();
}
}
(2)抽象类的案例实现
- 案例需求:请采用抽象类的思想实现猫和狗的案例,并在测试类中进行测试
代码实现
动物类
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
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;
}
public abstract void eat();
}
猫类
public class Cat extends Animal {
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
狗类
public class Dog extends Animal {
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
测试类
public class AnimalDemo {
public static void main(String[] args) {
//创建对象,按照多态的方式
Animal a = new Cat();
a.setName("加菲");
a.setAge(5);
System.out.println(a.getName()+","+a.getAge());
a.eat();
System.out.println("--------");
a = new Cat("加菲",5);
System.out.println(a.getName()+","+a.getAge());
a.eat();
}
}
3.6、接口
(1)接口的认识
- 接口的概述
- 接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。
- Java中的接口更多的体现在对行为的抽象!
接口的特点
成员特点
- 成员变量:只能是常量 ;默认修饰符:public static final
- 构造方法:没有,因为接口主要是扩展功能的,而没有具体存在
- 成员方法:只能是抽象方法;默认修饰符:public static
- 代码演示: ```java / 接口 / public interface Inter { public int num = 10; public final int num2 = 20; // public static final int num3 = 30; int num3 = 30;
// public Inter() {}
// public void show() {}
public abstract void method();
void show();
}
```java
/*
实现类
*/
public class InterImpl extends Object implements Inter {
public InterImpl() {
super();
}
@Override
public void method() {
System.out.println("method");
}
@Override
public void show() {
System.out.println("show");
}
}
/*
测试类
*/
public class InterfaceDemo {
public static void main(String[] args) {
Inter i = new InterImpl();
// i.num = 20;
System.out.println(i.num);
// i.num2 = 40;
System.out.println(i.num2);
System.out.println(Inter.num);
}
}
(3)接口的案例
- 案例需求
- 对猫和狗进行训练,他们就可以跳高了,这里加入跳高功能。
- 请采用抽象类和接口来实现猫狗案例,并在测试类中进行测试。
代码实现
/*
动物类
*/
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
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;
}
public abstract void eat();
}
/*
跳高接口
*/
public interface Jumpping {
public abstract void jump();
}
/*
猫类
*/
public class Cat extends Animal implements Jumpping {
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
}
/*
测试类
*/
public class AnimalDemo {
public static void main(String[] args) {
//创建对象,调用方法
Jumpping j = new Cat();
j.jump();
System.out.println("--------");
Animal a = new Cat();
a.setName("加菲");
a.setAge(5);
System.out.println(a.getName()+","+a.getAge());
a.eat();
// a.jump();
a = new Cat("加菲",5);
System.out.println(a.getName()+","+a.getAge());
a.eat();
System.out.println("--------");
Cat c = new Cat();
c.setName("加菲");
c.setAge(5);
System.out.println(c.getName()+","+c.getAge());
c.eat();
c.jump();
}
}
(4)类与接口的关系
类与类的关系:继承关系,只能是单继承,但是可以实现多层继承
- 类与接口的关系:实现关系,可以是单实现,也可以是多实现,还可以在继承一个类的同时实现多个接口
-
(5)抽象类与接口的区别
成员区别
- 抽象类:变量,常量;有构造方法;有抽象方法,也有非抽象方法
- 接口:常量;抽象方法
- 关系区别
- 类与类:继承,单继承
- 类与接口:实现,可以单实现,也可以多实现
- 接口与接口:继承,单继承,多继承
设计理念区别
案例需求
- 我们现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练。为了出国交流,跟乒乓球相关的人员都需要学习英语。请用所学知识分析,这个案例中有哪些具体类,哪些抽象类,哪些接口,并用代码实现。
代码实现
/*
抽象人类
*/
public abstract class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
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;
}
public abstract void eat();
}
/*
抽象运动员类
*/
public abstract class Player extends Person {
public Player() {
}
public Player(String name, int age) {
super(name, age);
}
public abstract void study();
}
/*
抽象教练类
*/
public abstract class Coach extends Person {
public Coach() {
}
public Coach(String name, int age) {
super(name, age);
}
public abstract void teach();
}
/*
学英语的接口
*/
public interface SpeakEnglish {
public abstract void speak();
}
/*
具体类:篮球教练
*/
public class BasketballCoach extends Coach {
public BasketballCoach() {
}
public BasketballCoach(String name, int age) {
super(name, age);
}
@Override
public void teach() {
System.out.println("篮球教练教如何运球和投篮");
}
@Override
public void eat() {
System.out.println("篮球教练吃羊肉,喝羊奶");
}
}
/*
具体类:乒乓球教练
*/
public class PingPangCoach extends Coach implements SpeakEnglish {
public PingPangCoach() {
}
public PingPangCoach(String name, int age) {
super(name, age);
}
@Override
public void teach() {
System.out.println("乒乓球教练教如何发球和接球");
}
@Override
public void eat() {
System.out.println("乒乓球教练吃小白菜,喝大米粥");
}
@Override
public void speak() {
System.out.println("乒乓球教练说英语");
}
}
/*
具体类:乒乓球运动员
*/
public class PingPangPlayer extends Player implements SpeakEnglish {
public PingPangPlayer() {
}
public PingPangPlayer(String name, int age) {
super(name, age);
}
@Override
public void study() {
System.out.println("乒乓球运动员学习如何发球和接球");
}
@Override
public void eat() {
System.out.println("乒乓球运动员吃大白菜,喝小米粥");
}
@Override
public void speak() {
System.out.println("乒乓球运动员说英语");
}
}
/*
具体类:篮球运动员
*/
public class BasketballPlayer extends Player {
public BasketballPlayer() {
}
public BasketballPlayer(String name, int age) {
super(name, age);
}
@Override
public void study() {
System.out.println("篮球运动员学习如何运球和投篮");
}
@Override
public void eat() {
System.out.println("篮球运动员吃牛肉,喝牛奶");
}
}
四、常用的API
4.1 、参数的传递
(1)参数传递的认识
- 类名作为方法的形参和返回值
- 方法的形参是类名,其实需要的是该类的对象
- 实际传递的是该对象的【地址值】
- 类名作为方法的返回值
- 方法的返回值是类名,其实返回的是该类的对象
- 实际传递的,也是该对象的【地址值】
代码示例
class Cat {
public void eat() {
System.out.println("猫吃鱼");
}
}
class CatOperator {
public void useCat(Cat c) { //Cat c = new Cat();
c.eat();
}
public Cat getCat() {
Cat c = new Cat();
return c;
}
}
public class CatDemo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
CatOperator co = new CatOperator();
Cat c = new Cat();
co.useCat(c);
Cat c2 = co.getCat(); //new Cat()
c2.eat();
}
}
抽象类做方法的形参和返回值
- 方法的形参是抽象类名,其实需要的是该抽象类的子类对象
- 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
代码示例
abstract class Animal {
public abstract void eat();
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
class AnimalOperator {
public void useAnimal(Animal a) { //Animal a = new Cat();
a.eat();
}
public Animal getAnimal() {
Animal a = new Cat();
return a;
}
}
public class AnimalDemo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
AnimalOperator ao = new AnimalOperator();
Animal a = new Cat();
ao.useAnimal(a);
Animal a2 = ao.getAnimal(); //new Cat()
a2.eat();
}
}
接口作为形参和返回值
- 方法的形参是接口名,其实需要的是该接口的实现类对象
- 方法的返回值是接口名,其实返回的是该接口的实现类对象
示例代码:
interface Jumpping {
void jump();
}
class JumppingOperator {
public void useJumpping(Jumpping j) { //Jumpping j = new Cat();
j.jump();
}
public Jumpping getJumpping() {
Jumpping j = new Cat();
return j;
}
}
class Cat implements Jumpping {
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
}
public class JumppingDemo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
JumppingOperator jo = new JumppingOperator();
Jumpping j = new Cat();
jo.useJumpping(j);
Jumpping j2 = jo.getJumpping(); //new Cat()
j2.jump();
}
}
(2)内部类的认识和使用
内部内的概念
- 在一个类中定义一个类。举例:在一个类A的内部定义一个类B,类B就被称为内部类
内部类定义格式 ```java /* 格式: class 外部类名{ 修饰符 class 内部类名{
} } */
class Outer { public class Inner {
}
}
- 内部类的访问特点
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建内部类的对象
- 代码示例
```java
/*
内部类访问特点:
内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象
*/
public class Outer {
private int num = 10;
public class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
Inner i = new Inner();
i.show();
}
}
(3)成员内部类
- 成员内部类的定义位置
- 在类中方法,跟成员变量是一个位置
- 外界创建成员内部类格式
- 格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
- 举例:Outer.Inner oi = new Outer().new Inner();
- 成员内部类的推荐使用方案
- 将一个类,设计为内部类的目的,大多数都是不想让外界去访问,所以内部类的定义应该私有化,私有化之后,再提供一个可以让外界调用的方法,方法内部创建内部类对象并调用。
代码示例
class Outer {
private int num = 10;
private class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
Inner i = new Inner();
i.show();
}
}
public class InnerDemo {
public static void main(String[] args) {
//Outer.Inner oi = new Outer().new Inner();
//oi.show();
Outer o = new Outer();
o.method();
}
}
(4)局部内部类
局部内部类定义位置
- 局部内部类是在方法中定义的类
局部内部类定义方式
- 局部内部类,外界是无法直接使用,需要在方法内部创建对象并使用
- 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
class Outer {
private int num = 10;
public void method() {
int num2 = 20;
class Inner {
public void show() {
System.out.println(num);
System.out.println(num2);
}
}
Inner i = new Inner();
i.show();
}
}
public class OuterDemo {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
(5)匿名类
匿名类的前提
- 存在一个类或者接口,这里的类可以是具体类也可以是抽象类
匿名类的格式
- 格式:new 类名 ( ) { 重写方法 } new 接口名 ( ) { 重写方法 }
- 举例:
/*
相当于有一个叫Inter的接口或类,被一个不知名的类实现或继承
*/
new Inter(){
@Override
public void method(){}
}
匿名类的本质:是一个继承了该类或者实现了该接口的子类匿名对象
匿名类的细节:匿名内部类可以通过多态的形式接受
Inter i = new Inter(){
@Override
public void method(){
}
}
匿名类直接调用方法 ```java interface Inter{ void method(); }
class Test{ public static void main(String[] args){ new Inter(){ @Override public void method(){ System.out.println(“我是匿名内部类”); } }.method(); // 直接调用方法 } }
<a name="dad132c05c3f41563a06d2f5021c9a43"></a>
### (6)匿名类在开发中的使用
- 使用场景:当发现某个方法需要,接口或抽象类的子类对象,我们就可以传递一个匿名类过去,来简化传统的代码
- 示例代码:
```java
interface Jumpping {
void jump();
}
class Cat implements Jumpping {
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
}
class Dog implements Jumpping {
@Override
public void jump() {
System.out.println("狗可以跳高了");
}
}
class JumppingOperator {
public void method(Jumpping j) { //new Cat(); new Dog();
j.jump();
}
}
class JumppingDemo {
public static void main(String[] args) {
//需求:创建接口操作类的对象,调用method方法
JumppingOperator jo = new JumppingOperator();
Jumpping j = new Cat();
jo.method(j);
Jumpping j2 = new Dog();
jo.method(j2);
System.out.println("--------");
// 匿名内部类的简化
jo.method(new Jumpping() {
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
});
// 匿名内部类的简化
jo.method(new Jumpping() {
@Override
public void jump() {
System.out.println("狗可以跳高了");
}
});
}
}
4.2、常用的API
(1)Math类
- Math类的概述
- Math类中包括基本的数学运算方法
- Math类中无构造方法,但内部方法都是静态的,可以通过:类名.方法名; 进行调用
- Math常用的方法 | 方法名 | 作用说明 | | | —- | —- | —- | | public static int abs(int a) | 返回参数的绝对值 | | | public static double ceil (double a) | 返回大于或等于参数的最小double值,等于一个整数(向上取整) | | | public static double floor (double a) | 返回小于或等于参数的最大double值,等于一个整数 | | | public static int round(float a) | 按照四舍五入返回最接近参数的int | | | public static int max(int a,int b) | 返回两个int值中的较大值 | | | public static int min(int a,int b) | 返回两个int值中的较小值 | | | public static double pow (double a,double b) | 返回a的b次幂的值 | | | public static double random() | 返回值为double的正值,[0.0,1.0) | |
(2)System类
- System常用的方法 | 方法名 | 功能说明 | | | —- | —- | —- | | public static void exit(int status) | 终止当前运行的 Java 虚拟机,非零表示异常终止 | | | public static long currentTimeMillis() | 返回当前时间(以毫秒为单位) | | | public static T arraycopy(参数1:要拷贝的数组源,参数2:要拷贝数组的起始索引,参数3:目的地数组,参数4:被拷贝数组的起始索引,参数5:要拷贝元素个数) | 此方法表示把一个数组的元素拷贝到另一个数组中。 | |
代码示例
/*
时间戳的演示
*/
public class SystemDemo {
public static void main(String[] args) {
// 获取开始的时间节点
long start = System.currentTimeMillis();
for (int i = 1; i <= 10000; i++) {
System.out.println(i);
}
// 获取代码运行结束后的时间节点
long end = System.currentTimeMillis();
System.out.println("共耗时:" + (end - start) + "毫秒");
}
}
(3)Object类中的toString方法的应用
Object类概述
- Object 是类层次结构的根,每个类都可以将 Object 作为超类。所有类都直接或者间接的继承自该类,换句话说,该类所具备的方法,所有类都会有一份
- 重写toString方法的方式
- 作用:在对象类中重写Object类中的toString方法和equals方法,起到可以打印对象名和比较对象名的作用
-
(4)冒泡排序
冒泡排序概述
- 一种排序的方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,依次对所有的数据进行操作,直至所有数据按要求完成排序
- 如果有n个数据进行排序,总共需要比较n-1次
- 每一次比较完毕,下一次的比较就会少一个数据参与
冒泡排序的代码实现
/*
冒泡排序:
一种排序的方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,
依次对所有的数据进行操作,直至所有数据按要求完成排序
*/
public class ArrayDemo {
public static void main(String[] args) {
//定义一个数组
int[] arr = {24, 69, 80, 57, 13};
System.out.println("排序前:" + arrayToString(arr));
// 这里减1,是控制每轮比较的次数
for (int x = 0; x < arr.length - 1; x++) {
// -1是为了避免索引越界,-x是为了调高比较效率
for (int i = 0; i < arr.length - 1 - x; i++) {
if (arr[i] > arr[i + 1]) {
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
System.out.println("排序后:" + arrayToString(arr));
}
//把数组中的元素按照指定的规则组成一个字符串:[元素1, 元素2, ...]
public static String arrayToString(int[] arr) {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
sb.append(arr[i]);
} else {
sb.append(arr[i]).append(", ");
}
}
sb.append("]");
String s = sb.toString();
return s;
}
}
(5)Arrays类
Arrays的常用方法 | 方法名 | 功能说明 | | | —- | —- | —- | | public static String toString(int[] a) | 返回指定数组的内容的字符串表示形式 | | | public static void sort(int[] a) | 按照数字顺序排列指定的数组 | |
工具类设计思想
- 构造方法用 private 修饰
- 成员用 public static 修饰
(6)时间类和日期类
- Date类的概述
- Date代表了一个特定的时间,精确到毫秒
- date的构造方法 | 构造方法名 | 功能说明 | | | —- | —- | —- | | public Date() | 分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒(表示当前电脑里的时间 ) | | | public Date(long date) | 分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数(表示1970年1月1日0时0分0秒加上参数的时间(注意:加上了中国的八个小时)) | |
- Date类的常用方法 | 方法名 | 功能说明 | | | —- | —- | —- | | 方法名说明public long getTime() | 获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值 | | | public void setTime(long time) | 设置时间,给的是毫秒值 | |
(7)simpleDateFormat类
- SimpleDateFormat类的概述
- 它是一个具体类,用于以区域设置敏感的方式格式和解析日期,重点是了解它的日期格式化和解析的功能
SimpleDateFormat的构造方法 | 构造方法名 | 功能说明 | | | —- | —- | —- | | public SimpleDateFormat() | 构造一个SimpleDateFormat,使用默认模式和日期格式 | | | public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat使用给定的模式和默认的日期格式 | |
SimpleDateFormat类的常用成员方法 | 方法名 | 功能说明 | | —- | —- | | public final String format(Date date) | 将日期格式化成日期/时间字符串 | | public Date parse(String source) | 从给定字符串的开始解析文本以生成日期 |
代码示例
public class SimpleDateFormatDemo {
public static void main(String[] args) throws ParseException {
//格式化:从 Date 到 String
Date d = new Date();
// SimpleDateFormat sdf = new SimpleDateFormat();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String s = sdf.format(d);
System.out.println(s);
System.out.println("--------");
//从 String 到 Date
String ss = "2048-08-09 11:11:11";
//ParseException
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dd = sdf2.parse(ss);
System.out.println(dd);
}
}
SimpleDateFormat工具类的案例
- 需求:定义一个日期工具类(DateUtils),包含两个方法:把日期转换为指定格式的字符串;把字符串解析为指定格式的日期,然后定义一个测试类(DateDemo),测试日期工具类的方法
代码实现 ```java public class DateUtils { private DateUtils() {}
/ 把日期转为指定格式的字符串 返回值类型:String 参数:Date date, String format / public static String dateToString(Date date, String format) { SimpleDateFormat sdf = new SimpleDateFormat(format); String s = sdf.format(date); return s; }
/*
把字符串解析为指定格式的日期
返回值类型:Date
参数:String s, String format
*/
public static Date stringToDate(String s, String format) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date d = sdf.parse(s);
return d;
}
}
- 测试类
```java
public class DateDemo {
public static void main(String[] args) throws ParseException {
//创建日期对象
Date d = new Date();
String s1 = DateUtils.dateToString(d, "yyyy年MM月dd日 HH:mm:ss");
System.out.println(s1);
String s2 = DateUtils.dateToString(d, "yyyy年MM月dd日");
System.out.println(s2);
String s3 = DateUtils.dateToString(d, "HH:mm:ss");
System.out.println(s3);
System.out.println("--------");
String s = "2048-08-09 12:12:12";
Date dd = DateUtils.stringToDate(s, "yyyy-MM-dd HH:mm:ss");
System.out.println(dd);
}
}
(8)Calendar类和LocalDateTime类
- Calendar类概述
- Calendar 为特定瞬间与一组日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法;Calendar 提供了一个类方法 getInstance 用于获取这种类型的一般有用的对象。该方法返回一个Calendar 对象。其日历字段已使用当前日期和时间初始化:Calendar rightNow = Calendar.getInstance();
Calendar类的常用方法 | 方法名 | 功能说明 | | —- | —- | | public int get(int field) | 返回给定日历字段的值 | | public abstract void add(int field, int amount) | 根据日历的规则,将指定的时间量添加或减去给定的日历字段 | | public final void set(int year,int month,int date) | 设置当前日历的年月日 |
示例代码 ```java public class CalendarDemo { public static void main(String[] args) {
//获取日历类对象
Calendar c = Calendar.getInstance();
//public int get(int field):返回给定日历字段的值
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH) + 1;
int date = c.get(Calendar.DATE);
System.out.println(year + "年" + month + "月" + date + "日");
//public abstract void add(int field, int amount):根据日历的规则,将指定的时间量添加或减去给定的日历字段
//需求1:3年前的今天
// c.add(Calendar.YEAR,-3); // year = c.get(Calendar.YEAR); // month = c.get(Calendar.MONTH) + 1; // date = c.get(Calendar.DATE); // System.out.println(year + “年” + month + “月” + date + “日”);
//需求2:10年后的10天前
// c.add(Calendar.YEAR,10); // c.add(Calendar.DATE,-10); // year = c.get(Calendar.YEAR); // month = c.get(Calendar.MONTH) + 1; // date = c.get(Calendar.DATE); // System.out.println(year + “年” + month + “月” + date + “日”);
//public final void set(int year,int month,int date):设置当前日历的年月日
c.set(2050,10,10);
year = c.get(Calendar.YEAR);
month = c.get(Calendar.MONTH) + 1;
date = c.get(Calendar.DATE);
System.out.println(year + "年" + month + "月" + date + "日");
} }
public class LocalDateTimeTest { public static void main(String[]args){ //获取当前时间 LocalDateTime now = LocalDateTime.now(); System.out.println(“now:”+now);//结果为:2021-05-11T15:49:25.496 //获取指定的时间 LocalDateTime of = LocalDateTime.of(2021, 05, 20, 11, 25, 30); System.out.println(“of:”+of);//结果为:2021-05-20T11:25:30 //getXxx方法(获取当月的第几天) System.out.println(“几号:”+now.getDayOfMonth()); //获取星期几 System.out.println(“周几:”+now.getDayOfWeek().getValue()); //一年当中的第几天 System.out.println(“一年当中的第几天:”+now.getDayOfYear()); //获取小时 System.out.println(“几点:”+now.getHour()); //获取分钟 System.out.println(“几分钟:”+now.getMinute()); //设置月份 System.out.println(“改过之后的日期:”+now.withDayOfMonth(12)); System.out.println(“没改的月份:”+now.getDayOfMonth()); //添加时间的操作 System.out.println(“五天后的日期:”+now.plusDays(5)); //减去时间的操作 System.out.println(“五天前的日期:”+now.minusDays(5)); } }
/**
- DateTimeFormatter类的测试 *
- @author HausenLee
- @date 2021/05/11
*/
public class DateTimeFormatterTest {
public static void main(String[]args){
} } ```//方法一:预定的标准的格式
DateTimeFormatter format = DateTimeFormatter.ISO_DATE_TIME;
LocalDateTime now = LocalDateTime.now();
System.out.println("方式一:格式化后的日期①:"+format.format(now));
//方式二:本地化相关的格式。如:ofLocalizedDateTime()方法
//形参里填如下的参数:FormatStyle.LONG/FormatStyle.MEDIUM/FormatStyle.SHORT
DateTimeFormatter format01 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
System.out.println("方式二:格式化后的日期format01:"+format01.format(now));//结果:2021年5月11日 下午05时00分06秒
DateTimeFormatter format02 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
System.out.println("方式二:格式化后的日期format02:"+format02.format(now));//结果 :2021-5-11 17:00:06
DateTimeFormatter format03 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
System.out.println("方式二:格式化后的日期format03:"+format03.format(now));//结果 :21-5-11 下午5:02
//方法三:自定义格式:如:ofPattern("yyyy-MM-dd HH:mm:ss")
DateTimeFormatter format04 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println("方法三:格式化后的日期format04:"+format04.format(now));
打印日历表的案例
public static void main(String[] args) {
//test1();
//获取当前的时间对象
LocalDate date = LocalDate.now();
//获取当前的月份
int month = date.getMonthValue();
//获取今天的日期
int today = date.getDayOfMonth();
//获取本月份的第一天的日期对象,并赋值给date覆盖掉旧值
date = date.minusDays(today - 1);
//获取当月1号对应的星期
DayOfWeek weekDay = date.getDayOfWeek();
//获取星期对应的数值
int value = weekDay.getValue();
//设置打印表头
System.out.println("周一 周二 周三 周四 周五 周六 周日");
//设置缩进对应表头
for (int i = 0; i < value; i++) {
System.out.print(" ");
}
//如果是月份是本月,则进入循环
while(date.getMonthValue() == month){
//打印日期
System.out.printf("%3d", date.getDayOfMonth());
if(date.getDayOfMonth() == today){
//如果日期是今天的日期,则在该日期上加上星号
System.out.print("*");
}else{
//否则用空格隔开
System.out.print(" ");
}
//然后date对象在日期上加一天
date = date.plusDays(1);
if(date.getDayOfWeek().getValue() == 1){
//如果日期到了星期一就换行
System.out.println();
}
}
/*if(date.getDayOfWeek().getValue() !=1){
System.out.println();
}*/
}
/*
相关的案例:求二月的天数
*/
public class CalendarTest {
public static void main(String[] args) {
//键盘录入任意的年份
Scanner sc = new Scanner(System.in);
System.out.println("请输入年:");
int year = sc.nextInt();
//设置日历对象的年、月、日
Calendar c = Calendar.getInstance();
c.set(year, 3, 1);
//3月1日往前推一天,就是2月的最后一天
c.add(Calendar.DATE, -1);
//获取这一天输出即可
int date = c.get(Calendar.DATE);
System.out.println(year + "年的2月份有" + date + "天");
}
}
(9)包装类
- 基本类型的包装类
- 作用:将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据
- 常用的操作之一:用于基本数据类型与字符串之间的转换
基本类型对应的包装类 | 基本数据类型 | 包装类 | | —- | —- | | byte | Byte | | short | Short | | int | Integer | | lang | Lang | | double | Double | | float | Float | | char | Character | | boolean | Boolean |
Integer类
Integer的常用构造方法 | 方法名 | 功能说明 | | —- | —- | | public Integer(int value) | 根据 int 值创建 Integer 对象(过时) | | public Integer(String s) | 根据 String 值创建 Integer 对象(过时) | | public static Integer valueOf(int i) | 返回表示指定的 int 值的 Integer 实例 | | public static Integer valueOf(String s) | 返回一个保存指定值的 Integer 对象 String |
示例代码
public class IntegerDemo {
public static void main(String[] args) {
//public Integer(int value):根据 int 值创建 Integer 对象(过时)
Integer i1 = new Integer(100);
System.out.println(i1);
//public Integer(String s):根据 String 值创建 Integer 对象(过时)
Integer i2 = new Integer("100");
// Integer i2 = new Integer("abc"); //NumberFormatException
System.out.println(i2);
System.out.println("--------");
//public static Integer valueOf(int i):返回表示指定的 int 值的 Integer 实例
Integer i3 = Integer.valueOf(100);
System.out.println(i3);
//public static Integer valueOf(String s):返回一个保存指定值的Integer对象 String
Integer i4 = Integer.valueOf("100");
System.out.println(i4);
}
}
String类型和int类型的转换
- int类型转换为String类型
- 转换方式一:直接在数字后面加空字符串
- 转换方式二:通过String类的静态方法valueOf()
示例代码
public class IntegerDemo {
public static void main(String[] args) {
//int --- String
int number = 100;
//方式1
String s1 = number + "";
System.out.println(s1);
//方式2
//public static String valueOf(int i)
String s2 = String.valueOf(number);
System.out.println(s2);
System.out.println("--------");
}
}
String类型转换int类型
- 转换方式一:先将字符串转换为Integer类型再调用valueOf()方法
- 转换方式二:通过Integer的静态方法parseInt()方法进行转换
- 示例代码:
public class IntegerDemo {
public static void main(String[] args) {
//String --- int
String s = "100";
//方式1:String --- Integer --- int
Integer i = Integer.valueOf(s);
//public int intValue()
int x = i.intValue();
System.out.println(x);
//方式2
//public static int parseInt(String s)
int y = Integer.parseInt(s);
System.out.println(y);
}
}
- int类型转换为String类型
类型转换案例
/*
需求:有一个字符串:“91 27 46 38 50”,请写程序实现最终输出结果是:“27 38 46 50 91”
*/
public class IntegerTest {
public static void main(String[] args) {
//定义一个字符串
String s = "91 27 46 38 50";
//把字符串中的数字数据存储到一个int类型的数组中
String[] strArray = s.split(" ");
// for(int i=0; i<strArray.length; i++) {
// System.out.println(strArray[i]);
// }
//定义一个int数组,把 String[] 数组中的每一个元素存储到 int 数组中
int[] arr = new int[strArray.length];
for(int i=0; i<arr.length; i++) {
arr[i] = Integer.parseInt(strArray[i]);
}
//对 int 数组进行排序
Arrays.sort(arr);
//把排序后的int数组中的元素进行拼接得到一个字符串,这里拼接采用StringBuilder来实现
StringBuilder sb = new StringBuilder();
for(int i=0; i<arr.length; i++) {
if(i == arr.length - 1) {
sb.append(arr[i]);
} else {
sb.append(arr[i]).append(" ");
}
}
String result = sb.toString();
//输出结果
System.out.println(result);
}
}
自动装箱和自动拆箱
- 自动装箱:把基本数据类型转换为对应的包装类
- 自动拆箱:把包装类转化为相对应的基本数据类型;
- 示例代码:
Integer i = 100; // 自动装箱
i += 200; // i = i + 200; i + 200 自动拆箱;i = i + 200; 是自动装箱
(10)Objects类
- Objects类的概述
- 是Object类的工具类
- Objects类常用的成员方法 | 方法名 | 功能说明 | | —- | —- | | public static String toString(对象) | 返回参数中对象的字符串表示形式 | | public static String toString(对象,默认字符串) | 返回对象的字符串表示形式(此方法表示如果o是空值就返回n) | | public static Boolean isNull(对象) | 判断对象是否为空 | | public static Boolean nonNull(对象) | 判断对象是否不为空 |
(11)BigDecimal 类
- BigDecimal 类的认识:此类进行精确的四则运算
- 构造方法
- BigDecimal(String val) ; (参数为要参与运算的数字)
- BigDecimal(int val) ; (参数为要参与运算的数字)
- 使用注意事项:一般用字符串类型的参数,因为更精确
- 常用方法
| 方法名 | 功能说明 |
| —- | —- |
| add(Object o); | 此方法做加法运算 |
| subtract(Object o); | 此方法做减法运算。 |
| multiply(Object o); | 此方法做乘法运算 |
| divide(Object o , int scale , BigDecimal.ROUND_UP); | 此方法表示的是除法运算;参数说明,参数
1
:参与运算的对象,参数
2
:要精
确的位数,参数
3
:是舍入模式;
此方法表示的是舍入模式为进一法 | | divide(Object o, int scale , BigDecimal.ROUND_FLOOR)
; | 此方法表示的是舍入模式为去尾法 | | divide(Object o ,int scale, BigDecimal.ROUND_HALF_UP); | 此方法表示的是四舍五入法。 |
(12)String类
- 字符串赋值结论:
- 常量与常量的拼接结果在常量池中,且常量池中不会存在相同内容的常量
- 只要其中有一个是变量,拼接的结果就在堆中开辟内存
五、异常
5.1、异常的认识
- 异常的概念
- 异常就是程序出现了不正常的情况,
- 异常的体系
- JVM默认处理异常的方式
- 如果程序出现了问题,我们没有做任何的处理,最终是jvm会默认的处理的,处理方式有如下两种方式,把异常的名称,错误的原因及异常出现的位置等信息输出在控制台;程序停止运行。
try-catch方式处理异常
- 定义格式
try {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
}
- 定义格式
执行流程
- 程序冲try里面的代码开始执行
- 出现异常就会跳到对应的catch中进行捕获
- 整个try-catch执行完后还可以执行之后的代码
代码演示
public class ExceptionDemo01 {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
System.out.println("这里能够访问到吗");
} catch (ArrayIndexOutOfBoundsException e) {
// System.out.println("你访问的数组索引不存在,请回去修改为正确的索引");
e.printStackTrace();
}
}
}
(1)Throwable类
Throwable的常用方法 | 方法名 | 功能说明 | | —- | —- | | public String getMessage() | 返回此 throwable 的详细消息字符串 | | public String toString() | 返回此可抛出的简短描述 | | public void printStackTrace() | 把异常的错误信息输出在控制台 |
代码示例
public class ExceptionDemo02 {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException();
System.out.println("这里能够访问到吗");
} catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException();
// e.printStackTrace();
//public String getMessage():返回此 throwable 的详细消息字符串
// System.out.println(e.getMessage());
//Index 3 out of bounds for length 3
//public String toString():返回此可抛出的简短描述
// System.out.println(e.toString());
//java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
//public void printStackTrace():把异常的错误信息输出在控制台
e.printStackTrace();
// java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
// at com.itheima_02.ExceptionDemo02.method(ExceptionDemo02.java:18)
// at com.itheima_02.ExceptionDemo02.main(ExceptionDemo02.java:11)
}
}
}
(2)编译时异常和运行时异常的区别
编译时异常
- 都是Exception的子类,必须显示处理,否则程序就会发送错误,导致代码无法编译
- 运行时异常
- 都是RuntimeException类及其子类;无需显示处理,也可以和编译时异常一样处理
(3)throws方式处理异常
- 定义格式 ```java public void 方法() throws 异常类名 {
}
- 代码示例
```java
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("开始");
// method();
try {
method2();
}catch (ParseException e) {
e.printStackTrace();
}
System.out.println("结束");
}
//编译时异常
public static void method2() throws ParseException {
String s = "2048-08-09";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(s);
System.out.println(d);
}
//运行时异常
public static void method() throws ArrayIndexOutOfBoundsException {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
}
}
- 注意事项
- 这个throws格式是跟在方法的括号后面的
- 编译时异常必须要进行处理,两种处理方案:try…catch …或者 throws,如果采用 throws 这种方案,将来谁调用谁处理
- 运行时异常可以不处理,出现问题后,需要我们回来修改代码
至于什么时候需要在方法中用到throws子句声明异常,什么异常必须使用throws子句,需要记住在遇到下面的四种情况下时应该抛出异常:
自定义异常类 ```java public class ScoreException extends Exception {
public ScoreException() {}
public ScoreException(String message) {
super(message);
}
}
- 老师类&测试类
```java
/*
老师类
*/
public class Teacher {
public void checkScore(int score) throws ScoreException {
if(score<0 || score>100) {
// throw new ScoreException();
throw new ScoreException("你给的分数有误,分数应该在0-100之间");
} else {
System.out.println("成绩正常");
}
}
}
/*
测试类
*/
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入分数:");
int score = sc.nextInt();
Teacher t = new Teacher();
try {
t.checkScore(score);
} catch (ScoreException e) {
e.printStackTrace();
}
}
}