Java入门学习笔记

目录

  • 一.Java 入门
    • 1. Java 概述
      • (1) Java 语言的发展
      • (2) Java 三大平台
        • JavaSE
        • ~~JavaME~~
        • JavaEE
      • (3) Java 的主要特性
      • (4) JRE 和 JDK
    • 2.下载和安装
      • (1)下载
      • (2)安装
    • 3.环境变量
      • (1) 配置
      • (2) JDK目录介绍
    • 4. 人机交互
      • (1)打开cmd窗口
      • (2)常用cmd命令
    • 5.第一个Java程序
    • 6.Java编辑器(IDEA)
  • 二.Java基础语法
    • 1.注释
    • 2.关键字
    • 3.字面量
    • 4.变量
    • 5.命名
      • (1)命名规则
      • (2)命名规范
    • 6.基本数据类型
    • 7.数据转换
      • 隐式转换
      • 强制转换
    • 8.拼接操作
    • 9.键盘录入
    • 10.运算符
      • 算术运算符:
      • 自增自减运算符:
      • 赋值运算符
      • 关系运算符
      • 逻辑运算符
      • 三元运算符
      • 运算符优先级
  • 三.流程控制语句
    • 1.顺序结构
    • 2.判断 if语句
      • if语句格式1
      • if语句格式2
      • if语句格式3
    • 3.条件控制语句
    • 4.选择 switch语句
    • 5.异常处理
    • 6.循环结构
      • for循环
      • while循环
      • ~~do...while循环~~
  • 四.数组
    • 1.数组的定义
    • 2.静态数组
    • 3.动态数组
    • 4.数组元素访问
    • 5.数组的遍历
  • 五. 方法
    • 1. 定义和调用
      • 无参数
      • 带参数
      • 带返回值
      • 通用格式
    • 2. 方法重载
    • 3. 注意事项
  • 六.面向对象
    • 1.类和对象
      • 类的定义
      • 对象的使用
    • 2.包
    • 3.成员变量和局部变量
    • 4.权限修饰符
    • 5.封装
      • private关键字
    • 6.this关键字
    • 7.static关键字
      • 静态变量
      • 静态方法
    • 8.final关键字
      • 修饰类
      • 修饰方法
      • 修饰变量
        • 基本数据类型:
        • 引用数据类型:
    • 9.构造方法
    • 10.标准的JavaBean类
  • 七.字符串
    • 1.API
    • 2.String类
      • 字符串的比较
      • 字符串的遍历
      • 统计字符
      • 字符串的拼接
      • 字符串反转
      • 金额转换
      • 字符串截取
      • 字符串替换
    • 3.StringBuilder
    • 4. StringJoiner
  • 八.集合(ArrayList)
    • 构造方法
    • 成员方法
  • 九.继承
    • 1. super关键字
    • 2.方法重写
    • 3.继承后的构造方法
    • 4.super()和this()
  • 十.多态
    • 1.多态的使用
    • 2.多态的运行特点
    • 3.多态的弊端
    • 4.引用类型转换
      • 向上转型(自动转换)
      • 向下转型(强制转换)
      • instanceof 关键字
  • 十一.抽象类
    • 1.abstract关键字
      • 抽象方法
      • 抽象类
    • 2.注意事项
  • 十二.接口
    • 类与接口的实现
    • 接口与接口的继承
  • 十三.内部类
    • 1.成员内部类
    • 2.静态内部类
    • 3.局部内部类
    • 4.匿名内部类

一.Java 入门

1. Java 概述

语言:人与人交流沟通的表达方式

计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言

Java是一门非常火的计算机语言。(也叫做编程语言)

我们想要让计算机做一些事情,那么就可以通过Java语言告诉计算机就可以了

(1) Java 语言的发展

Java入门学习笔记_第1张图片

(2) Java 三大平台

JavaSE

​ 是其他两个版本的基础。

JavaME

​ Java语言的小型版,用于嵌入式消费类电子设备或者小型移动设备的开发。

​ 其中最为主要的还是小型移动设备的开发(手机)。渐渐的没落了,已经被安卓和苹果给替代了

JavaEE

​ 用于Web方向的网站开发。(主要从事后台服务器的开发)

​ 在服务器领域,Java是当之无愧的老大。

(3) Java 的主要特性

  • 面向对象
  • 安全性
  • 多线程
  • 简单易用
  • 开源
  • 跨平台

Java入门学习笔记_第2张图片

Java语言跨平台的原理:

操作系统本身是不认识Java语言的,针对于不同的操作系统,Java提供了不同的虚拟机,虚拟机会把Java语言翻译成操作系统能看得懂的语言。

(4) JRE 和 JDK

Java入门学习笔记_第3张图片

JVM(Java Virtual Machine)Java虚拟机

JRE(Java Runtime Environment)Java运行环境,包含了JVM和Java的核心类库(Java API)

JDK(Java Development Kit)Java开发工具,包含了JRE和开发工具

2.下载和安装

这里只做简单介绍,小白请看

jdk 安装与配置环境(windows系统)

(1)下载

官方链接:

http://www.oracle.com

注意:

  • 不同的操作系统,需要下载对应版本的JDK

  • 电脑是windows32位的,就装32位的,64位的就装64位的JDK

  • Java从9版本开始,不提供32位版本的安装包了

(2)安装

​ 默认的安装路径是在C:\Program Files下。

注意:(若自定义安装路径)

安装路径不要有中文,不要有空格等一些特殊符号

3.环境变量

开发Java程序,需要使用JDK提供的开发工具(比如javac.exe、java.exe等命令),而这些工具在JDK的安装目录的bin目录下,如果不配置环境变量,那么这些命令只可以在bin目录下使用,而我们想要在任意目录下都能使用,所以就要配置环境变量,把这个软件的路径配置到环境变量中的PATH里面。

注意:下载老版本的JDK是没有自动配置的,而且自动配置的只包含了4个工具

(1) 配置

步骤:

  • 右键我的电脑,选择属性
  • 点击左侧的高级系统设置
  • 选择高级,再点击下面的环境变量
  • 找系统变量里面的PATH
  • 把软件的完整路径,配置到PATH当中就可以了

方式:

JAVA_HOME:告诉操作系统JDK安装在了哪个位置(未来其他技术要通过这个找JDK)

请添加图片描述

Path:告诉操作系统JDK提供的javac(编译)、java(执行)命令安装到了哪个位置

Java入门学习笔记_第4张图片

(2) JDK目录介绍

目录名称 说明
bin 该路径下存放了JDK的各种工具命令。javac和java就放在这个目录。
conf 该路径下存放了JDK的相关配置文件。
include 该路径下存放了一些平台特定的头文件。
jmods 该路径下存放了JDK的各种模块。
legal 该路径下存放了JDK各模块的授权文档。
lib 该路径下存放了JDK工具的一些补充JAR包。

4. 人机交互

在windows操作系统中,利用利用cmd命令去操作计算机,比如:打开文件,打开文件夹,创建文件夹等。

(1)打开cmd窗口

  1. 按下快捷键:win + R

  2. 在运行窗口中输出 cmd

  3. 输出回车

(2)常用cmd命令

操作 说明
E: 盘符名称*** 表示切换到E盘盘符切换
dir 查看当前路径下的内容
cd 目录 进入单级目录
cd … 回退到上一级目录
cd 目录1\目录2… 进入多级目录
cd \ 回退到盘符目录
cls 清屏
exit 退出命令提示符窗口

注意:

在windows操作系统中,文件名或者文件夹名是忽略大小写的。

5.第一个Java程序

  1. 新建文本文档文件,修改名称为HelloWorld.java。

注意:后缀名为java的才是java文件。

  1. 用记事本打开HelloWorld.java文件,输入下面代码
public class HelloWorld {
	public static void main(String[] args) {
		System.out.println("HelloWorld");
	}
}
  1. 保存

Java入门学习笔记_第5张图片

注意:未保存的文件在左上角会有*符号标记

  1. 编译文件。编译后会产生一个class文件。

    java文件:程序员自己编写的代码。

    class文件:交给计算机执行的文件。

  2. 运行代码

    注意:运行的是编译之后的class文件。

用到两个命令:
javac + 文件名 + 后缀名 (就是编译java文件)
java + 文件名(运行编译之后的class文件)

运行结果:

Java入门学习笔记_第6张图片

6.Java编辑器(IDEA)

IDEA概述:

​ IDEA全称IntelliJ IDEA,是用于Java语言开发的集成环境,它是目前公认的Java程序开发最好的工具。

集成环境:

​ 把代码编写,编译,执行,调试等多种功能综合到一起的开发工具。

下载官网:

https://www.jetbrains.com/idea

安装详细步骤请查看:

IDEA 下载与安装

二.Java基础语法

1.注释

单行注释:

// 单行注释

多行注释:

/*
多行注释
...
*/
注意:多行注释不能嵌套使用。

文档注释:

/**
也是多行注释
...
*/

2.关键字

被Java赋予了特定含义的英文单词,所有关键字都是小写字母

abstract assert boolean break byte
case catch char class const
continue default do double else
enum extends final finally float
for goto if implements import
instanceof int interface long native
new package private protected public
return strictfp short static super
switch synchronized this throw throws
transient try void volatile while

3.字面量

作用:告诉程序员,数据在程序中的书写格式。

字面量类型 说明 写法
整数 不带小数的数字 666,-88
小数 带小数的数字 13.14,-5.21
字符 必须使用单引号,有且仅能一个字符 ‘A’,‘0’, ‘我’
字符串 必须使用双引号,内容可有可无 “HelloWorld”
布尔值 布尔值,表示真假 true 、false
空值 一个特殊的值,空值 值是:null
public class literal {
    public static void main(String[] args) {
        System.out.println(10); // 输出一个整数
        System.out.println(5.5); // 输出一个小数
        System.out.println('a'); // 输出一个字符
        System.out.println(true); // 输出boolean值true
        System.out.println("HelloWorld"); // 输出字符串
        System.out.println("null"); // 输出null
    }
}

运行结果:

Java入门学习笔记_第7张图片

4.变量

可以看作存储数据的容器,但只能存一个值

定义:

数据类型 变量名 = 数据值;
int x=1;

数据类型:规定变量当中能存储什么类型的数据

变量名:容器的命名

数据值:存储在容器中的数据

分 号:Java语法规定以分号结束

注意:

  1. 变量名不能重复
  2. 在一条语句中,可以定义多个变量
  3. 变量在使用之前必须要赋值

5.命名

(1)命名规则

必须遵循,否则代码会报错

  • 必须由数字、字母、下划线_、美元符号$组成
  • 不能以数字开头
  • 不能是关键字
  • 区分大小写

(2)命名规范

见名知意,如果不这样做,代码虽然不会报错,但是同事看你的代码会很难受

小驼峰命名法:适用于变量名和方法名

  • 如果是一个单词,那么全部小写,比如:name

  • 如果是多个单词,那么从第二个单词开始,首字母大写,比如:firstName、maxAge

大驼峰命名法:适用于类名

  • 如果是一个单词,那么首字母大写。比如:Demo、Test。

  • 如果是多个单词,那么每一个单词首字母都需要大写。比如:HelloWorld

注意:

  1. 尽量不要用拼音
  2. 在给变量名、方法名、类名命名时,不要使用下划线或美元符号

6.基本数据类型

数据类型 关键字 内存占用 取值范围
整数 byte 1 -128~127
short 2 -32768~32767
int 4 负的2的31次方 ~ 2的31次方-1
long 8 负的2的63次方 ~ 2的63次方-1
浮点数 float 4 1.401298e-45 ~ 3.402823e+38
double 8 4.9000000e-324 ~ 1.797693e+308
字符 char 2 0-65535
布尔 boolean 1 true,false

补充:

  • e+38表示是乘以10的38次方,同样,e-45表示乘以10的负45次方
  • 在java中整数默认是int类型,浮点数默认是double类型
  • 整数类型和小数类型的取值范围大小关系:
double > float > long > int > short > byte

注意:

  1. 如果要定义一个long类型的变量,那么在数据值的后面需要加上L后缀。(大小写都可以)
  2. 如果要定义一个float类型的变量,那么在数据值的后面需要加上F后缀。(大小写都可以)

7.数据转换

隐式转换

就是把一个取值范围小的数据或变量,自动赋值给另一个取值范围大的变量

转换规则:

  • 取值范围小的,和取值范围大的进行运算,小的会先提升为大的,进行运算
  • byte、short、char三种类型的数据运算,都会直接先提升为int,然后再进行运算。

取值范围大小关系:

double > float > long > int > short > byte

强制转换

我们要把一个取值范围大的数据或变量赋值给另一个取值范围小的变量,是不允许的

如果一定要这么干,就需要加入强制转换

格式:

//目标数据类型 变量名 = (目标数据类型)被强转的数据;
public class Mandatory {
    public static void main(String[] args) {
        double x = 1.3;
        int y = (int) x;
        System.out.println(y);	//1
    }
}

注意:

强制转换有可能会导致数据发生错误(数据精度丢失)

8.拼接操作

字符串的+操作

  • 当+操作中出现字符串时,此时+是连接符,会将前后的数据进行拼接,并产生一个新的字符串
  • 当连续进行+操作时,从左到右逐个执行
  • 字符串只有+操作,没有其他操作
1 + "abc" + 1	//1abc1
1 + 2 + "abc" + 2 + 1	//3abc21

字符的+操作

当+操作中出现字符时,此时会拿着字符到计算机内置的ASCII码表中去查对应的数字,然后进行计算

char a = 'a';	//ASCII码表中a=97
int result = a + 0;
System.out.println(result);	//97

9.键盘录入

Java已经帮我们写好了,不需要我们自己写了,我们只需导入Scanner这个类就可以直接使用了

如:

//导包,导入Scanner类
import java.util.Scanner;
public class ScannerUse{
	public static void main(String[] args){
		//创建对象,使用Scanner这个类
		Scanner sc = new Scanner(System.in);
		//接收数据,用变量x接收传入的数据
		System.out.println("请输入一个数字:");
		int x = sc.nextInt();
		System.out.println("输入的x值为:" + x);
	}
}

运行结果:

Java入门学习笔记_第8张图片

方法 说明
next() 可以接受任意数据,返回的是一个字符串
nextLine() 可以接受任意数据,返回的是一个字符串
nextInt() 只接受整数,录入小数或者其他字母,就会报错
nextDouble() 能接收整数和小数,但是都会以小数返回,录入字母会报错

注意:

  • next(),nextInt(),nextDouble()在接收数据的时候,会遇到空格,回车,制表符其中一个就会停止接收数据。

  • next(),nextInt(),nextDouble()在接收数据的时候,会遇到空格,回车,制表符其中一个就会停止接收数据。但是这些符号 + 后面的数据还在内存中并没有接收。如果后面还有其他键盘录入的方法,会自动将这些数据接收。

  • nextLine()方法遇到回车停止接收数据,是把一整行全部接收完毕

10.运算符

对常量或者变量进行操作的符号

算术运算符:

算术运算符 运算说明
+
-
*
/
% 取模、取余,除法运算,获取的是余数

表达式:

System.out.println( 1 + 1);		//3
System.out.println( 1 * 3);		//3
System.out.println( 10 / 3);	//3
System.out.println(10.0 / 3);	//3.3333333333333335

注意:

  1. 整数相除结果只能得到整数,如果结果想要是小数,必须要有小数参数
  2. 小数直接参与运算,得到的结果有可能是不精确的

自增自减运算符:

自增自减运算符 运算说明
++ 把变量里面的值+1
把变量里面的值-1

表达式:

int a = 10;
a++;
System.out.println(a);	//11

++a;
System.out.println(a);	//12

注意:

不管是先++,还是后++,单独写在一行的时候,运算结果是一模一样的

赋值运算符

赋值运算符 运算说明
= 等号右边的结果,赋值给左边的变量
+= 符号左边跟右边进行运算,将最终的结果赋值给左边
-= 符号左边跟右边进行运算,将最终的结果赋值给左边
*= 符号左边跟右边进行运算,将最终的结果赋值给左边
/= 符号左边跟右边进行运算,将最终的结果赋值给左边
%= 符号左边跟右边进行运算,将最终的结果赋值给左边

如:

public class Expand {
    public static void main(String[] args) {
        byte a = 10;
        byte b = 10;
        a += b;		//这里做了一个强制转换为byte
        //a = (byte)(a + b);
        System.out.println(a);//20
    }
}

注意:

扩展的赋值运算符中隐层还包含了一个强制转换。

关系运算符

又叫比较运算符,其实就是拿着左边跟右边进行了判断而已。

关系运算符 运算说明
== 判断左边跟右边是否相等,如果成立就是true,如果不成立就是false
!= 判断左边跟右边是否不相等,如果成立就是true,如果不成立就是false
> 判断左边是否大于右边,如果成立就是true,如果不成立就是false
>= 判断左边是否大于等于右边,如果成立就是true,如果不成立就是false
< 判断左边是否小于右边,如果成立就是true,如果不成立就是false
<= 就是判断左边是否小于等于右边,如果成立就是true,如果不成立就是false

注意:

关系运算符最终的结果一定是布尔类型的。要么是true,要么是false

逻辑运算符

逻辑运算符 运算说明
& ;两边都为真,结果才为真,只要有一个为假,那么结果就是假
| ;两边都为假,结果才为假,只要有一个为真,那么结果就是真
^ 异或;两边都相同,结果为false,如果两边不同,结果为true
! 取反;false取反就是true,true取反就是false
&& ;两边都为真,结果才为真,只要有一个为假,那么结果就是假(具有短路效果)
|| ;两边都为假,结果才为假,只要有一个为真,那么结果就是真具有(短路效果)

短路效果:

当左边不能确定整个表达式的结果,右边才会执行。当左边能确定整个表达式的结果,那么右边就不会执行了。优点是提高了代码的运行效率

注意:

&& 和 & 、||和|的运行结果都是一模一样的,只不过具有短路效果

三元运算符

又叫做:三元表达式或者问号冒号表达式。

三元运算符 运算说明
?: 计算关系表达式的值

表达式:

//关系表达式 ? 表达式1 :表达式2;
/*
如果关系表达式的值为真,那么执行表达式1,为假则执行表达式2
*/
public class Ternary {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
       	int max =  a>b ? a:b;
        System.out.println(max);//20
    }
}

运行结果:

请添加图片描述

注意:

三元运算符的最终结果一定要被使用,要么赋值给一个变量,要么直接输出。

运算符优先级

优先级 运算符 结合性
1 ( ) [ ]  . 从左到右
2 !  ~  ++  – 从右到左
3 *  /  % 从左到右
4 +  - 从左到右
5 <<  >>  >>> 从左到右
6 <  <=  >  >= instanceof 从左到右
7 ==  != 从左到右
8 & 从左到右
9 ^ 从左到右
10 从左到右
11 && 从左到右
12 || 从左到右
13 ? : 从左到右
14 = += -= *= /= &= |= ^= ~= «= »= >>>= 从左到右
15 从左到右

总结:

括号级别最高,逗号级别最低,单目 > 算术 > 位移 > 关系 > 逻辑 > 三目 > 赋值

三.流程控制语句

在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的。所以,我们必须清楚每条语句的执行流程。而且,很多时候要通过控制语句的执行顺序来实现我们想要的功能,如:最常见顺序结构就是程序中最简单最基本的流程控制,按照代码的先后顺序执行

1.顺序结构

执行流程:

  • 按照代码的先后顺序,依次执行

Java入门学习笔记_第9张图片

2.判断 if语句

if语句格式1

if (关系表达式) {
    语句体;	
}

执行流程:

  1. 先计算关系表达式的值
  2. 如果关系表达式的值为true则执行语句体
  3. 如果关系表达式的值为false则不执行语句体
  4. 继续执行后面的语句

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QgBp70to-1665368466777)(ing/1545616039363.png)]

如:

import java.util.Scanner;
public class Beauty {
	public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入谈过几个对象:");
        int sum = sc.nextInt();
        if(sum > 2) {
            System.out.println("你真行!!!");
        }
	}
}

运行结果:

Java入门学习笔记_第10张图片

注意:

  1. 如果关系表达式是一个布尔类型的变量,可以直接把变量写在小括号中

  2. 如果大括号中的语句体只有一条,那么大括号可以省略不写

if语句格式2

if (关系表达式) {
    语句体1;	
} else {
    语句体2;	
}

执行流程:

  1. 先计算关系表达式的值
  2. 如果关系表达式的值为true则执行语句体1
  3. 如果关系表达式的值为false则执行语句体2
  4. 继续执行后面的语句

Java入门学习笔记_第11张图片

如:

import java.util.Scanner;
public class Beauty {
	public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入谈过几个对象:");
        int sum = sc.nextInt();
        if(sum > 2) {
            System.out.println("你真行!!!");
		} else {
			System.out.println("你真捞!!!");
		}		
	}
}

运行结果:

Java入门学习笔记_第12张图片

if语句格式3

if (关系表达式1) {
    语句体1;	
} else if (关系表达式2) {
    语句体2;	
} 
...
else {
    语句体n+1;
}

执行流程:

  1. 先计算关系表达式1的值
  2. 如果值为true则执行语句体1;如果值为false则计算关系表达式2的值
  3. 如果值为true则执行语句体2;如果值为false则计算关系表达式3的值
  4. 如果没有任何关系表达式为true,则执行语句体n+1

Java入门学习笔记_第13张图片

如:

import java.util.Scanner;
public class Beauty {
	public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入谈过几个对象:");
        int sum = sc.nextInt();
        if(sum > 2) {
            System.out.println("你真行!!!");
		} else if(sum==2){
			System.out.println("你还行!!!");
        } else if(sum==1){
            System.out.println("你不行!!!");
        } else {
            System.out.println("你真捞!!!");
		}		
	}
}

运行结果:

Java入门学习笔记_第14张图片

3.条件控制语句

  • break

不能单独存在的。可以用在switch和循环中,表示结束,终止循环

  • continue

不能单独存在的。只能存在于循环当中,表示跳过本次循环,继续执行下去

4.选择 switch语句

switch (表达式) {
	case 1:
		语句体1;
		break;
	case 2:
		语句体2;
		break;
	...
	default:
		语句体n+1;
		break;
}

执行流程:

  1. 先计算出表达式的值
  2. 然后跟case值依次比较,一旦有对应的值,就会执行相应的语句,在执行的过程中,遇到break就会结 束
  3. 如果所有的case值都不匹配,则会执行default语句体部分,然后程序结束掉

如:

import java.util.Scanner;
public class Date {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("表示星期几(请输入一个整数)?");
        int week = sc.nextInt();

        switch (week){
            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;
            default:
                System.out.println("输入错误,没有这个星期");
                break;
        }
    }
}

运行结果:

Java入门学习笔记_第15张图片

注意:

  1. default可以写到任意位置,也可以省略
  2. 不写break会引发case穿透
  3. switch在JDK12后可以简写

如:

//键盘录入星期数,输出工作日(1~5)、休息日(6~7)
Scanner sc = new Scanner(System.in);
System.out.println("请输入星期:");
int week = sc.nextInt();

//利用case穿透简化代码
switch (week){
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        System.out.println("工作日");
        break;
    case 6:
    case 7:
        System.out.println("休息日");
        break;
    default:
        System.out.println("没有这个星期");
        break;
}

//利用JDK12简化代码书写
switch (week) {
    case 1, 2, 3, 4, 5 -> System.out.println("工作日");
    case 6, 7 -> System.out.println("休息日");
    default -> System.out.println("没有这个星期");
}

5.异常处理

try {
    //可能出现异常的代码
}catch(异常类型1 变量名1) {
    //处理异常的方式1
}catch(异常类型2 变量名2) {
    //处理异常的方式2
}
....
finally {
    //一定会执行的代码
}

异常类型:

Java入门学习笔记_第16张图片

如:

public class Demo01 {
    public static void main(String[] args) {
        try {
            int a = 10;
            int b = 0;
            System.out.println(a/b);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("程序运行错误");
        }finally {
            System.out.println("程序运行结束!!!");
        }
    }
}

运行结果:

Java入门学习笔记_第17张图片

6.循环结构

循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复 执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则循环将一直执行下去形成死循环

for循环

for (初始化语句;条件判断语句;条件控制语句) {
	循环体语句;
}

初始化语句:  表示循环开启时的起始状态
条件判断语句:表示循环反复执行的条件,就是判断循环是否能一直执行下去
条件控制语句:表示循环执行中每次变化的内容,就是控制循环是否能执行下去
循环体语句:  表示循环反复执行的内容

如:

//求1-100之间的偶数和
public class Sums {
    public static void main(String[] args) {
		int sum = 0;
		for(int i=1; i<=100; i++) {
			if(i%2 == 0) {
                sum += i;
			}
		}
		System.out.println("1-100之间的偶数和是:" + sum);
    }
}

运行结果:

请添加图片描述

while循环

初始化语句;
while(条件判断语句){
	循环体;
	条件控制语句;
}
初始化语句:  表示循环开启时的起始状态
条件判断语句:表示循环反复执行的条件,就是判断循环是否能一直执行下去
条件控制语句:表示循环执行中每次变化的内容,就是控制循环是否能执行下去
循环体语句:  表示循环反复执行的内容

如:

//求1-100之间的偶数和
public class Sums {
    public static void main(String[] args) {
        int sum = 0;
        int i = 0;
        while(i<=100) {
            i++;
            if(i%2 == 0) {
                sum += i;

            }
        }
        System.out.println("1-100之间的偶数和是:" + sum);
    }
}

运行结果:

请添加图片描述

do…while循环

几乎不用

初始化语句;
do{
    循环体;
    条件控制语句;
}while(条件判断语句);

如:

//求1-100之间的偶数和
public class Sums {
    public static void main(String[] args) {
		int sum = 0;
        int i = 0;
        do{
            if(i%2 == 0) {
                sum += i;
                i++
            }while(i<=100);
		}
		System.out.println("1-100之间的偶数和是:" + sum);
    }
}

运行结果:

请添加图片描述

特点:

先执行,再判断

四.数组

概念:

指的是一种容器,可以用来存储同种数据类型的多个值,但是在存储数据的时候,需要考虑隐式转换

比如:定义了一个int类型的数组,那么boolean、double类型的数据是不能存到这个数组中的,但是byte类型,short类型,int类型的数据又可以存到这个数组里面的

1.数组的定义

格式:

数据类型 [] 数组名
或:
数据类型  数组名 []  
    
int [] sum
int sum []
    
两种格式所表达的效果都是一样的

数据类型:限定了数组能存什么类型的数据

方括号:表示现在定义的是一个数组

数组名:数组的名字

2.静态数组

格式:

数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,元素4...};
简化:
数据类型[] 数组名 = {元素1,元素2,元素3,元素4...};

int[] sum = new int[]{11,22,33};

double[] sum ={1.1,1.2,1.3};

数据类型:限定了数组能存什么类型的数据,前、后的数据类型一定要保持一致

方括号:表示现在定义的是一个数组

数组名:数组的名字

new:就是给数组在内存中开辟了一个空间

3.动态数组

格式:

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

int[] len = new int[3];

动态数组的默认初始化值:

整数类型:0

小数类型:0.0

布尔类型:false

字符类型:‘\u0000’(空格)

引用类型:null

两种数组的区别:

静态初始化:int[] sum = new int{1,2,3,4,5};

动态初始化:int[] sum= new int[3];

静态初始化:手动指定数组的元素,系统会根据元素的个数,计算出数组的长度

动态初始化:手动指定数组长度,由系统给出默认初始化值

使用取舍:

  • 若明确元素个数,但是不明确具体的数据,使用动态初始化
  • 若数据明确,使用静态初始化

4.数组元素访问

格式:

数组名[索引];
int[] sum = {1,2,3,4,5};

//打印数组的地址
System.out.println(sum);//[I@6d03e736

//获取sum数组中,3索引上的值
int x = sum[3];
System.out.println(x);//4

//将sum数组中,3索引上的值修改为10
sum[3] = 10;
System.out.println("修改之后为:" + sum[3]);//10

索引:也叫角标、下标,就是数组容器中每一个小格子对应的编号

索引的特点:

  • 索引一定是从0开始的
  • 连续不间断
  • 逐个+1增长

5.数组的遍历

遍历:就是把数组里面所有的内容一个一个全部取出来

数组的长度:数组名.length;

for(int i = 0; i < sum.length; i++){
    //在循环的过程中,i依次表示数组中的每一个索引
    System.out.println(sum[i]);
}

定义一个数组,存入1~5,打乱数组中所有元素的顺序

import java.util.Random;

public class Sums {
    public static void main(String[] args) {
        //1.定义数组存储1~5
        int[] sum = new int[]{1, 2, 3, 4, 5};
        //2.循环遍历数组,从0索引开始打乱数据的顺序
        Random r = new Random();
        for (int i = 0; i < sum.length; i++) {
            //生成一个随机索引
            int randomIndex = r.nextInt(sum.length);
            //拿着随机索引指向的元素跟i指向的元素进行交换
            int temp = sum[i];
            sum[i] = sum[randomIndex];
            sum[randomIndex] = temp;
        }
        //当循环结束之后,数组中所有的元素的乱顺序就打乱了
        for (int i = 0; i < sum.length; i++) {
            System.out.print(sum[i] + " ");
        }
    }
}

运行结果:

请添加图片描述

五. 方法

概念:

方法(method)是程序中最小的执行单元,

方法必须先创建才可以使用,该过称为方法定义,

方法创建后并不是直接可以运行的,需要手动调用后,才执行

1. 定义和调用

无参数

格式:

//定义
public static void 方法名 () {
	// 方法体;
}

//调用
方法名();

例:

定义一个方法,用于打印两个数字中的较大数

public class MethodTest {
    public static void main(String[] args) {
        //在main()方法中调用定义好的方法
        getMax();
    }

    //定义一个方法,用于打印两个数字中的较大数,例如getMax()
    public static void getMax() {
        //方法中定义两个变量,用于保存两个数字
        int a = 1;
        int b = 10;

        //使用分支语句分两种情况对两个数字的大小关系进行处理
        if(a > b) {
            System.out.print("max="+a);
        } else {
            System.out.print("max="+b);
        }
    }
}

注意:方法必须先定义,后调用,否则程序将报错

带参数

格式:

//定义
public static void 方法名 (参数1) {
	方法体;
}

public static void 方法名 (参数1, 参数2, 参数3...) {
	方法体;
}

//调用
方法名(参数);

方法名(参数1,参数2);

参数:由数据类型和变量名组成 (数据类型 变量名)

形参和实参

  • 形参:方法定义中的参数
  • 实参:方法调用中的参数

例:

public class MethodTest {
    public static void main(String[] args) {
        //在main()方法中调用定义好的方法(使用常量)
        getMax(10,20);
        //调用方法的时候,人家要几个,你就给几个,人家要什么类型的,你就给什么类型的,否则报错

        //在main()方法中调用定义好的方法(使用变量)
        int a = 1;
        int b = 10;
        getMax(a, b);
    }

    //定义一个方法,用于打印两个数字中的较大数,例如getMax()
    //为方法定义两个参数,用于接收两个数字
    public static void getMax(int a, int b) {
        //使用分支语句分两种情况对两个数字的大小关系进行处理
        if(a > b) {
            System.out.print("max="+a);
        } else {
            System.out.print("max="+b);
        }
    }
}

注意:

方法定义时,参数中的数据类型与变量名都不能缺少,缺少任意一个程序将报错

方法调用时,参数的数量与类型必须与方法定义中的设置相匹配,否则程序将报错

带返回值

格式

//定义
public static 数据类型 方法名 (参数) { 
	return 数据 ;
}

//调用
方法名 (参数);
数据类型 变量名 = 方法名 (参数) ;

例:

public class MethodTest {
    public static void main(String[] args) {
        //在main()方法中调用定义好的方法并使用变量保存
        int result = getMax(1,10);
        System.out.println("max="+result);

        System.out.println("max="+getMax(10,20));
    }

    //定义一个方法,用于获取两个数字中的较大数
    public static int getMax(int a, int b) {
        //使用分支语句分两种情况对两个数字的大小关系进行处理
        //根据题设分别设置两种情况下对应的返回结果
        if(a > b) {
            return a;
        } else {
            return b;
        }
    }
}

注意:

方法定义时return后面的返回值与方法定义上的数据类型要匹配,否则程序将报错

方法的返回值通常会使用变量接收,否则该返回值将无意义

通用格式

格式:

//定义
public static 返回值类型 方法名(参数) {
   方法体; 
   return 数据 ;
}
//调用
方法名 (参数);

public static :修饰符

返回值类型:方法操作完,返回数据的数据类型;如果方法操作完,没有返回值,写void

方法名:调用方法时候使用的标识

参数:由数据类型和变量名组成,多个参数之间用逗号隔开

方法体:完成功能的代码块

return:如果方法操作完毕,有数据返回,用于把数据返回给调用者

2. 方法重载

概念:

方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载

  1. 多个方法在同一个类中
  2. 多个方法具有相同的方法名
  3. 多个方法的参数不同、类型不同或者数量不同

例:

public class MethodTest {
    public static void main(String[] args) {
        //调用方法
        System.out.println(compare(10, 20));
        System.out.println(compare((byte) 10, (byte) 20));
        System.out.println(compare((short) 10, (short) 20));
        System.out.println(compare(10L, 20L));
    }

    //int
    public static boolean compare(int a, int b) {
        System.out.println("int");
        return a == b;
    }

    //byte
    public static boolean compare(byte a, byte b) {
        System.out.println("byte");
        return a == b;
    }

    //short
    public static boolean compare(short a, short b) {
        System.out.println("short");
        return a == b;
    }

    //long
    public static boolean compare(long a, long b) {
        System.out.println("long");
        return a == b;
    }

}

注意:

  • 重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式
  • 重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载

3. 注意事项

方法不能嵌套定义

如:

public class MethodTest {
    public static void main(String[] args) {

    }

    public static void methodOne() {
		public static void methodTwo() {
       		// 这里会引发编译错误!!!
    	}
    }
}

void表示无返回值,可以省略return,也可以单独的书写return,后面不加数据

如:

public class Methodtest {
    public static void main(String[] args) {

    }
    public static void methodOne() {
        //return 10; 编译错误,因为没有具体返回值类型
        return;	
        //System.out.println(10); return语句后面不能跟数据或代码
    }
}

六.面向对象

1.类和对象

概念:

客观存在的事物皆为对象 ,说万物皆对象

  • 类:类是对现实生活中一类具有共同属性和行为的事物的抽象
  • 对象:是能够看得到摸的着的真实存在的实体

类是对事物的一种描述,对象则为具体存在的事物

类的定义

类的组成是由属性和行为两部分组成

  • 属性:在类中通过成员变量来体现(类中方法外的变量)
  • 行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)
/*
public class 类名 {
	// 成员变量
	变量1的数据类型 变量1;
	变量2的数据类型 变量2;
	…
	// 成员方法
	方法1;
	方法2;	
}
*/

public class Phone {
    //成员变量
    String brand;
    int price;

    //成员方法
    public void call() {
        System.out.println("打电话");
    }

    public void sendMessage() {
        System.out.println("发短信");
    }
}

对象的使用

/*
    创建对象
        格式:类名 对象名 = new 类名();
        范例:Phone p = new Phone();

    使用对象
        1:使用成员变量
            格式:对象名.变量名
            范例:p.brand
        2:使用成员方法
            格式:对象名.方法名();
            范例:p.call()
 */
public class PhoneDemo {
    public static void main(String[] args) {
        //创建对象
        Phone p = new Phone();

        //使用成员变量
        System.out.println(p.brand);
        System.out.println(p.price);

        p.brand = "小米";
        p.price = 2999;

        System.out.println(p.brand);
        System.out.println(p.price);

        //使用成员方法
        p.call();
        p.sendMessage();
    }
}

2.包

包在操作系统中其实就是一个文件夹。用来管理不同的Java类,方便以后管理和维护。

在IDEA项目中,建包的操作如下:

Java入门学习笔记_第18张图片

包的命名:

路径名.路径名.xxx.xxx
// 例如:com.itheima.oa
  • 包名必须用”.“连接
  • 包名尽量全部英文小写
  • 包名的每个路径名必须是一个合法的标识符,且不能是Java的关键字

导包:

什么时候需要导包?

  1. 在使用Java中提供的非核心包中的类时
  2. 使用自己写的其他包中的类时

什么时候不需要导包?

  1. 在使用Java核心包(java.lang)中的类时
  2. 在使用自己写的同一个包中的类时

3.成员变量和局部变量

成员变量 局部变量
类中位置不同 类中方法外 方法内部或方法声明上
内存中位置不同 堆内存 栈内存
生命周期不同 随着对象的存在而存在,随着对象的消失而消失 随着方法的调用而存在,醉着方法的调用完毕而消失
初始化值不同 有默认初始化值 没有默认初始化值,必须先定义,赋值才能使用

4.权限修饰符

Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限

修饰符 访问权限
public 公共的,所有地方都可以访问
protected 本类 ,本包,其他包中的子类都可以访问
默认(没有修饰符) 本类 ,本包可以访问
private 私有的,当前类可以访问

不同权限的访问能力:

public protected 默认 private
同一类中
同一包中的类
不同包的子类
不同包中的无关类

public具有最大权限。private则是最小权限。

5.封装

概念:

封装是面向对象三大特征之一(封装,继承,多态)

对象代表什么,就得封装对应的数据,并提供数据对应的行为

将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问

private关键字

private是一个修饰符,可以用来修饰成员(成员变量,成员方法)

被private修饰的成员,只能在本类进行访问,针对private修饰的成员变量,如果需要被其他类使用,提供相应的操作

  • 提供“get变量名()”方法,用于获取成员变量的值,方法用public修饰
  • 提供“set变量名(参数)”方法,用于设置成员变量的值,方法用public修饰

例:

//定义一个学生类
class Student {
    //成员变量
    String name;
    private int age;

    //提供get/set方法
    //set方法:给成员变量赋值
    //get方法:对外提供成员变量
    public void setAge(int a) {
        if(a<0 || a>100) {
            System.out.println("你给的年龄有误");
        } else {
            age = a;
        }
    }

    public int getAge() {
        return age;
    }

    //成员方法
    public void show() {
        System.out.println(name + "," + age);
    }
}

//学生测试类
public class StudentDemo {
    public static void main(String[] args) {
        //创建对象
        Student s = new Student();
        //给成员变量赋值
        s.name = "李逍遥";
        s.setAge(30);
        //调用show方法
        s.show();
    }
}

6.this关键字

this修饰的变量用于指代成员变量,其主要作用是(区分局部变量和成员变量的重名问题

  • 方法的形参如果与成员变量同名,不带this修饰的变量指的是形参,而不是成员变量
  • 方法的形参没有与成员变量同名,不带this修饰的变量指的是成员变量
public class Student {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void show() {
        System.out.println(name + "," + age);
    }
}

7.static关键字

static关键字用来修饰成员变量和成员方法,被static修饰的成员是属于类的,是放在静态区中;没有static修饰的成员变量和方法,则是属于对象的。

静态变量

所有的对象都可以共享这个变量

有static修饰成员变量,说明这个成员变量是属于类的,这个成员变量称为类变量或者静态成员变量。 直接可以用 类名访问。因为类只有一个,所以静态成员变量在内存区域中也只存在一份。

定义:

//修饰符 static 数据类型 变量名 = 初始值;

例:

public class Student {
    //静态变量
    public static String name = "圣美同学"; // 属于类,只有一份
    //实例变量,不能直接调用
    private int age=10;	//实例成员变量属于每个对象,必须创建类的对象才可以访问
    
    //访问
    public static void  main(String[] args){
        System.out.println(Student.name); // 圣美同学
        Student.name = "小美同学";
        System.out.println(Student.name); // 小美同学
    }
}

静态方法

所有的对象都可以共享这个方法

有static修饰成员方法,说明这个成员方法是属于类的,这个成员方法称为类方法或者静态方法。 可以直接用 类名访问。因为类只有一个,所以静态方法在内存区域中也只存在一份。

例:

public class Student {
    //静态变量
    public static String name = "圣美同学"; // 属于类,只有一份。

    //静态方法
    public static void style() {
        System.out.println("圣美在看美女");
    }
    
    //访问
    public static void main(String[] args){
        Student.style();
    }
}

实例变量、方法:

无static修饰的成员变量或者成员方法,称为实例变量,实例方法,实例变量和实例方法必须创建类的对象,然后通过对象来访问。

public class Student {
    // 实例变量
    private String name;

    // 无 static修饰,实例方法。属于每个对象,必须创建对象调用
    public void age(){
        System.out.println(name +"18岁");
    }

    //访问
    public static void main(String[] args){
        // 创建对象,必须创建类的对象才可以访问。 
        Student stu = new Student();
        stu.name = "圣美";
        stu.age();

    }
}

总结:

static修饰的成员属于类,会存储在静态区,是随着类的加载而加载的,且只加载一次,所以只有一份,节省内存。存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。它优先于对象存在,所以,可以被所有对象共享。

8.final关键字

final修饰的内容不可变,可以用于修饰类、方法和变量。

  • 类:被修饰的类,不能被继承。
  • 方法:被修饰的方法,不能被重写。
  • 变量:被修饰的变量,有且仅能被赋值一次。

修饰类

final修饰的类,不能被继承。

格式:

final class 类名 {
}

如:

final class Fu {
}
// class Zi extends Fu {} // 报错,不能继承final的类

修饰方法

final修饰的方法,不能被重写。
格式:

修饰符 final 返回值类型 方法名(参数列表){
    //方法体
}

如:

class Fu2 {
	final public void show1() {
		System.out.println("Fu2 show1");
	}
	public void show2() {
		System.out.println("Fu2 show2");
	}
}

class Zi2 extends Fu2 {
//	@Override
//	public void show1() {
//		System.out.println("Zi2 show1");
//	}
	@Override
	public void show2() {
		System.out.println("Zi2 show2");
	}
}

修饰变量

基本数据类型:

变量的值不能修改

局部变量:

基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。

public class FinalDemo1 {
    public static void main(String[] args) {
        // 声明变量,使用final修饰
        final int a;
        // 第一次赋值 
        a = 10;
        // 第二次赋值
        a = 20; // 报错,不可重新赋值

        // 声明变量,直接赋值,使用final修饰
        final int b = 10;
        // 第二次赋值
        b = 20; // 报错,不可重新赋值
    }
}

成员变量:

成员变量涉及到初始化的问题,初始化方式有显示初始化构造方法初始化,不能同时使用final修饰,只能选择其中一个:

显示初始化(在定义成员变量的时候赋值)

public class Student {
    final int num = 10;
}

构造方法初始化(在构造方法中赋值一次)

//注意:每个构造方法中都要赋值一次!
public class Student {
    final int num = 10;
    final int num2;

    public Student() {
        this.num2 = 20;
//     this.num2 = 20;
    }
    
     public Student(String name) {
        this.num2 = 20;
//     this.num2 = 20;
    }
}
引用数据类型:

变量的地址值不能修改,内部属性值可以修改

final int[] ARR = {1,2,3,4,5};
        //ARR = new int[10];
        ARR[0] = 10;
        ARR[1] = 20;

9.构造方法

构造方法是一种特殊的方法

作用:创建对象的时候,由虚拟机自动调用,是给成员变量进行初始化的

格式:

public class 类名{
	修饰符 类名( 参数 ) {

	}
}

特点:

  1. 方法名与类名相同,大小写要一致
  2. 没有返回值类型,没有void
  3. 没有具体返回值,没有retrun

功能:主要是完成对象数据的初始化

例:

//学生类
class Student {
    private String name;
    private int age;
	
    //空参构造
    public Student() {}

    public Student(String name) {
        this.name = name;
    }

    public Student(int age) {
        this.age = age;
    }
	
    //有参构造
    public Student(String name,int age) {
        this.name = name;
        this.age = age;
    }

    public void show() {
        System.out.println(name + "," + age);
    }
}

//测试类
public class StudentDemo {
    public static void main(String[] args) {
        //创建对象
        Student s1 = new Student();
        s1.show();

        //public Student(String name)
        Student s2 = new Student("李逍遥");
        s2.show();

        //public Student(int age)
        Student s3 = new Student(30);
        s3.show();

        //public Student(String name,int age)
        Student s4 = new Student("李逍遥",30);
        s4.show();
    }
}

注意:

  1. 构造方法的创建

    如果没有定义构造方法,系统将给出一个默认的无参数构造方法
    如果定义了构造方法,系统将不再提供默认的构造方法

  2. 构造方法的重载

    如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法

  3. 可以使用带参构造,为成员变量进行初始化

10.标准的JavaBean类

① 类名需要见名知意

② 成员变量使用private修饰

③ 提供至少两个构造方法

  • 无参构造方法
  • 带全部参数的构造方法

④ get和set方法

​ 提供每一个成员变量对应的setXxx()/getXxx()

⑤ 如果还有其他行为,也需要写上

七.字符串

1.API

API (Application Programming Interface) :应用程序编程接口

java中的API指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来,我们可以直接使用这些类,但如何使用呢?那就要学习这些类的使用,通过帮助文档来学习这些API如何使用

帮助文档位置:

jdk帮助文档一般在jdk的docs目录下,可以用浏览器直接打开,每个API都有索引及用法说明

2.String类

概念:

String 类代表字符串,Java 程序中的所有字符串文字(如"abc")都被实现为此类的实例。也就是说,Java 程序中所有的双引号字符串,都是 String 类的对象。String 类在 java.lang 包下,所以使用的时候不需要导包

特点:

  • 字符串不可变,它们的值在创建后不能被更改
  • 虽然 String 的值是不可变的,但是它们可以被共享
  • 字符串效果上相当于字符数组( char[] ),但是底层原理是字节数组( byte[] )

常用的构造方法

方法 说明
public String() 创建一个空白字符串对象,不含有任何内容
public String(char[] chs) 根据字符数组的内容,来创建字符串对象
public String(byte[] bys) 根据字节数组的内容,来创建字符串对象
String s = “abc”; 直接赋值的方式创建字符串对象,内容就是abc

例:

import java.util.Scanner;
public class StringDemo01 {
    public static void main(String[] args) {
        //public String():创建一个空白字符串对象,不含有任何内容
        String s1 = new String();
        System.out.println("s1:" + s1);

        //public String(char[] chs):根据字符数组的内容,来创建字符串对象
        char[] chs = {'a', 'b', 'c'};
        String s2 = new String(chs);
        System.out.println("s2:" + s2);

        //public String(byte[] bys):根据字节数组的内容,来创建字符串对象
        byte[] bys = {97, 98, 99};
        String s3 = new String(bys);
        System.out.println("s3:" + s3);

        //String s = “abc”;	直接赋值的方式创建字符串对象,内容就是abc
        String s4 = "abc";
        System.out.println("s4:" + s4);
    }
}

注意:

  • 通过构造方法创建

    ​ 通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同

  • 直接赋值方式创建

    ​ 以"abc"方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护

字符串的比较

**==**比较

比较基本数据类型时:比较的是具体的值

比较引用数据类型时:比较的是对象地址值

equals方法

比较两个字符串内容是否相同、区分大小写

import java.util.Scanner;
public class StringDemo02 {
    public static void main(String[] args) {
        //构造方法的方式得到对象
        char[] chs = {'a', 'b', 'c'};
        String s1 = new String(chs);
        String s2 = new String(chs);

        //直接赋值的方式得到对象
        String s3 = "abc";
        String s4 = "abc";

        //比较字符串对象地址是否相同
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s3 == s4);
        System.out.println("--------");

        //比较字符串内容是否相同
        System.out.println(s1.equals(s2));
        System.out.println(s1.equals(s3));
        System.out.println(s3.equals(s4));
    }
}

字符串的遍历

charAt():会根据索引获取对应的字符

import java.util.Scanner;

public class StringDemo03 {
    public static void main(String[] args) {
        //charAt():会根据索引获取对应的字符
        //length(): 会返回字符串的长度
        
        //1.键盘录入一个字符串
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入字符串");
        String str = sc.next();

        //2.遍历
        for (int i = 0; i < str.length(); i++) {
            //i 依次表示字符串的每一个索引

            //根据索引获取字符串里面的每一个字符
            //ctrl + alt + V 自动生成左边的接受变量
            char c = str.charAt(i);
            System.out.println(c);
        }
    }
}

统计字符

import java.util.Scanner;

public class StringDemo04 {
    public static void main(String[] args) {
        //键盘录入一个字符串,统计大写,小写,数字出现的次数

        //1.键盘录入一个字符串
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串");
        String str = sc.next();


        //2.统计 --- 计数器count
        //此时我要统计的有3样东西,所以要定义3个计数器分别进行统计
        int bigCount = 0;
        int smallCount = 0;
        int numberCount = 0;
        //得到这个字符串里面每一个字符
        for (int i = 0; i < str.length(); i++) {
            //i 表示字符串中的索引

            //c 表示字符串中的每一个字符
            char c = str.charAt(i);

            //对c进行判断
            if (c >= 'a' && c <= 'z') {
                smallCount++;
            } else if (c >= 'A' && c <= 'Z') {
                bigCount++;
            } else if (c >= '0' && c <= '9') {
                numberCount++;
            }
        }

        //3.当循环结束之后,三个变量记录的就是对应的个数
        System.out.println("大写字符有:" + bigCount + "个");
        System.out.println("小写字符有:" + smallCount + "个");
        System.out.println("数字字符有:" + numberCount + "个");
    }
}

字符串的拼接

import java.util.Scanner;

public class StringDemo05 {
    public static void main(String[] args) {
        /*定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,
        并在控制台输出结果。例如,数组为 int[] arr = {1,2,3};
        执行方法后的输出结果为:[1, 2, 3]*/

        int[] arr = {1, 2, 3, 4, 5};
        String str = arrToString(arr);
        System.out.println(str);
    }

    //作用:把一个数组变成字符串
    public static String arrToString(int[] arr) {
        String s = "";
        //拼接左括号
        s = s + "["; //此时是拿着长度为0的字符串,跟[进行拼接,产生一个新的字符串。
        //把新的字符串再赋值给s,此时变量s记录的就是新的字符串"["的地址值
        
        //遍历数组,得到数组里面的每一个元素并进行拼接
        for (int i = 0; i < arr.length; i++) {
            //假设第一次循环:i = 0 获取的就是0索引上的元素
            //在拼接的时候:"[" + 1 + ", " 拼接完毕之后产生一个新的字符串 "[1, "
            //第二次循环:i = 1 获取的就是1索引上的元素
            //在拼接的时候: 此时s就是第一次循环结束后拼接完毕的结果:"[1, "
            //在拼接的时候:"[1, " + 2 + ", " 拼接完毕之后产生一个新的字符串 "[1, 2, "
            //...
            if (i == arr.length - 1) {
                //如果是最后一个元素,那么不需要拼接逗号空格
                s = s + arr[i];
            } else {
                //如果不是最后一个元素,需要拼接元素和逗号空格
                s = s + arr[i] + ", ";
            }
        }

        //等循环结束之后,再拼接最后一个右括号
        s = s + "]";
        return s;
    }
}

字符串反转

import java.util.Scanner;

public class StringDemo06 {
    public static void main(String[] args) {
        /*定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果
        例如,键盘录入 abc,输出结果 cba*/


        //1.定义一个字符串
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串");
        String str = sc.next();
        //2.定义一个方法,反转字符串
        //abc  --->  cba
        //可以把字符串倒着遍历,再拼接
        String result = reverse(str);
        System.out.println(result);

    }

    //把传递进来的字符串进行反转
    public static String reverse(String str){//abc
        //核心思想:倒着遍历并进行拼接就可以了
        String s = "";
        for (int i = str.length() - 1; i >= 0; i--) {
            //我们就可以拿到里面的每一个字符并拼接
            s = s + str.charAt(i);
        }
        return s;

    }
}

金额转换

​ 把2135变成:零佰零拾零万贰仟壹佰叁拾伍元

​ 把789变成:零佰零拾零万零仟柒佰捌拾玖元

import java.util.Scanner;

public class StringDemo03 {
    public static void main(String[] args) {
        //1.键盘录入一个金额
        Scanner sc = new Scanner(System.in);
        int money;
        while (true) {
            System.out.println("请录入一个金额");
            money = sc.nextInt();
            if (money >= 0 && money <= 9999999) {
                break;
            } else {
                System.out.println("金额无效");
            }
        }

        //定义一个变量用来表示钱的大写
        String moneyStr = "";

        //2.得到money里面的每一位数字,再转成中文
        while (true) {
            //从右往左获取数据,因为右侧是数据的个位
            int ge = money % 10;
            String capitalNumber = getCapitalNumber(ge);
            //把转换之后的大写拼接到moneyStr当中
            moneyStr = capitalNumber + moneyStr;
            //第一次循环 : "伍" + "" = "伍"
            //第二次循环 : "叁" + "伍" = "叁伍"
            //去掉刚刚获取的数据
            money = money / 10;

            //如果数字上的每一位全部获取到了,那么money记录的就是0,此时循环结束
            if (money == 0) {
                break;
            }
        }

        //3.在前面补0,补齐7位
        int count = 7 - moneyStr.length();
        for (int i = 0; i < count; i++) {
            moneyStr = "零" + moneyStr;
        }
        System.out.println(moneyStr);//零零零贰壹叁伍

        //4.插入单位
        //定义一个数组表示单位
        String[] arr = {"佰","拾","万","仟","佰","拾","元"};
        //               零    零   零   贰   壹   叁   伍

        //遍历moneyStr,依次得到 零    零   零   贰   壹   叁   伍
        //然后把arr的单位插入进去

        String result = "";
        for (int i = 0; i < moneyStr.length(); i++) {
            char c = moneyStr.charAt(i);
            //把大写数字和单位拼接到result当中
            result = result + c + arr[i];
        }

        //5.打印最终结果
        System.out.println(result);
    }


    //定义一个方法把数字变成大写的中文
    //1 -- 壹
    public static String getCapitalNumber(int number) {
        //定义数组,让数字跟大写的中文产生一个对应关系
        String[] arr = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
        //返回结果
        return arr[number];
    }
}

字符串截取

**substring()**方法

import java.util.Scanner;

public class StringDemo8 {
    public static void main(String[] args) {
        /*以字符串的形式从键盘接受一个手机号,隐藏中间四位号码
        最终效果为:155****4568*/

        //1.键盘录入一个手机号码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入手机号码");
        String phoneNumber = sc.next();

        //2.截取手机号码中的前三位
        String star = phoneNumber.substring(0, 3);

        //3.截取手机号码中的最后四位
        //此时我用substring方法
        //因为现在我们要截取到最后,第二个参数可以省略不写
        String end = phoneNumber.substring(7);

        //4.拼接
        String result = star + "****" + end;

        System.out.println(result);
    }
}

字符串替换

**replace()**方法

import java.util.Scanner;

public class StringDemo09 {
    public static void main(String[] args) {
        /*以字符串的形式从键盘接受一个手机号,隐藏中间四位号码
        最终效果为:155****4568*/

        //1.键盘录入一个手机号码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入手机号码");
        String phoneNumber = sc.next();

        //2.截取手机号码中间四位
        String star = phoneNumber.substring(3, 7);

        //3.截取手机号码中的最后四位
        //此时我用replace方法
        //替换中间四位
        String result = phoneNumber.replace(star, "****");

        System.out.println(result);
    }
}

3.StringBuilder

StringBuilder 可以看成是一个容器,创建之后里面的内容是可变的。

当我们在拼接字符串和反转字符串的时候会使用到

append()添加元素 reverse()反转 toString()把StringBuilder变回字符串

例:

import java.util.Scanner;

public class StringDemo03 {
    //键盘接受一个字符串,程序判断出该字符串是否是对称字符串,并在控制台打印是或不是

    public static void main(String[] args) {
        //1.键盘录入一个字符串
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串");
        String str = sc.next();

        //2.反转键盘录入的字符串
        //创建对象,append:添加元素	reverse:反转	toString:把StringBuilder变回字符串
        String result = new StringBuilder().append(str).reverse().toString();
        
        //3.比较
        if(str.equals(result)){
            System.out.println("当前字符串是对称字符串");
        }else{
            System.out.println("当前字符串不是对称字符串");
        }
    }
}

注意:

因为StringBuilder是Java已经写好的类,java在底层对他做了一些特殊处理,使打印对象不是地址值而是属性值。

4. StringJoiner

StringJoiner跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的

作用:提高字符串的操作效率,代码编写特别简洁

例:

import java.util.StringJoiner;

//定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果
public class StringJoiner0 {
    public static void main(String[] args) {
        //1.定义数组
        int[] arr = {1, 2, 3};

        //2.创建对象
        StringJoiner sj = new StringJoiner(", ", "[", "]");
        //3.添加元素
        for (int i = 0; i < arr.length; i++) {
           sj.add(arr[i] + "");
            }
        int len = sj.length();
        System.out.println(len);
        //4.打印
        System.out.println(sj);

        String str = sj.toString();
        System.out.println(str);
    }
}

八.集合(ArrayList)

概念:

集合是一种存储空间可变的存储模型,存储的数据容量可以发生改变,只能存储引用数据类型

若要存储基本数据类型得用对应的包装类

泛型:

约束集合中存储元素的数据类型

ArrayList array = new ArrayList();		//泛型<数据类型>

基本数据类型对应的包装类

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

构造方法

方法名 说明
public ArrayList() 创建一个空的集合对象

成员方法

方法名 说明
public boolean add(要添加的元素) 将指定的元素追加到此集合的末尾,返回值表示是否追加成功
public boolean remove(要删除的元素) 删除指定元素,返回值表示是否删除成功
public E remove(int index) 删除指定索引处的元素,返回被删除的元素
public E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
public E get(int index) 返回指定索引处的元素
public int size() 返回集合中的元素的个数

例:

import java.util.ArrayList;

public class ArrayListDemo01 {
    public static void main(String[] args) {
        //创建集合
        ArrayList<String> array = new ArrayList<String>();

        //添加元素
        array.add("hello");
        array.add("小姐姐");

        System.out.println(array.add("你好呀!"));

        //删除指定的元素,返回删除是否成功
//        System.out.println(array.remove("小姐姐"));
//        System.out.println(array.remove("java"));

        //删除指定索引处的元素,返回被删除的元素
//        System.out.println(array.remove(1));  //该索引处若没有元素,则会报错

        //修改指定索引处的元素,返回被修改的元素
//        System.out.println(array.set(1, "黑丝小仙女"));   //该索引处若没有元素,则会报错

        //查找元素,返回指定索引处的元素
        System.out.println(array.get(0));
        System.out.println(array.get(1));
//        System.out.println(array.get(5));   //该索引处若没有元素,则会报错


        //获取元素长度,返回集合中的元素的个数
//        System.out.println(array.size());

        //输出集合
        System.out.println("array:" + array);
    }
}

九.继承

概念:

继承是面向对象三大特征之一(封装,继承,多态)

继承就是子类继承父类的属性行为,使得子类对象可以直接具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。

优点:

  1. 提高代码的复用性(减少代码冗余,相同代码重复利用)
  2. 使类与类之间产生了关系

格式:

关键字 extends ,可以声明一个子类继承另外一个父类

class 父类 {
	...
}

class 子类 extends 父类 {
	...
}

注意:

  1. Java是单继承,一个类只能继承一个直接父类
  2. Java不支持多继承、但是支持多层继承
  3. Java中所有的类都直接或间接继承Object类

并不是父类的所有内容都可以给子类继承的,子类不能继承父类的构造方法,但是是子类可以继承父类的私有成员(成员变量、方法),只是子类无法直接访问,可以通过getter/setter方法访问父类的private成员变量。

1. super关键字

如果子类父类中出现重名的成员变量,子类会优先访问自己对象中的成员变量。

如果此时我们想访问父类中的成员变量如何解决呢?我们可以使用super关键字。修饰父类成员变量,类似于 this关键字。

super代表的是父类对象的引用,this代表的是当前对象的引用。

格式:

super.父类成员变量名

例:

class Fu {
    // Fu中的成员变量。
    int num = 5;
}

class Zi extends Fu {
    // Zi中的成员变量
    int num = 6;

    public void show() {
        int num = 1;

        // 访问方法中的num
        System.out.println("method num=" + num);//1
        // 访问子类中的num
        System.out.println("Zi num=" + this.num);//6
        // 访问父类中的num
        System.out.println("Fu num=" + super.num);//5
    }
}

class Demo01 {
    public static void main(String[] args) {
        // 创建子类对象
        Zi z = new Zi();
        // 调用子类中的show方法
        z.show();
    }
}

注意:

Fu 类中的成员变量是非私有的,子类中可以直接访问。若Fu 类中的成员变量私有了,子类是不能直接访问的。通常编码时,我们遵循封装的原则,使用private修饰成员变量,那么如何访问父类的私有成员变量呢?对!可以在父类中提供公共的getXxx方法和setXxx方法。

2.方法重写

概念:

子类中出现与父类重名的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现

例:

class Fu {
    public void show() {
        System.out.println("Fu show");
    }
}
class Zi extends Fu {
    //子类重写了父类的show方法
    @Override	//注解,可以不写
    public void show() {
        System.out.println("Zi show");
    }
}
public class Demo02{
    public static void main(String[] args) {
        Zi z = new Zi();
        // 子类中有show方法,只执行重写后的show方法
        z.show();  // Zi show
    }
}

@Override重写注解:

  • @Override:注解,重写注解校验!

  • 这个注解标记的方法,就说明这个方法必须是重写父类的方法,否则编译阶段报错。

  • 可以省略

注意:

  1. 方法重写是发生在子父类之间的关系。
  2. 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
  3. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。

3.继承后的构造方法

子类不能继承父类的构造方法

原因:

  1. 构造方法的名字是与类名一致的,所以子类是无法继承父类构造方法。
  2. 构造方法的作用是初始化对象成员变量数据的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。

例:

class Person {
    private String name;
    private int age;

    public Person() {
        System.out.println("父类无参");
    }

    // getter/setter省略
}

class Student extends Person {
    private int score;

    public Student() {
        //super(); // 调用父类无参,默认就存在,可以不写,必须在第一行
        System.out.println("子类无参");
    }

    public Student(int score) {
        //super();  // 调用父类无参,默认就存在,可以不写,必须在第一行
        this.score = score;
        System.out.println("子类有参");
    }

}

public class Demo03 {
    public static void main(String[] args) {
        Student s1 = new Student();
        System.out.println("------------");
        Student s2 = new Student(0);
    }
}

总结:

  • 子类构造方法执行的时候,都会在第一行默认先调用父类无参数构造方法一次。
  • 子类构造方法的第一行都隐含了一个**super()**去调用父类无参数构造方法,**super()**可以省略不写。

4.super()和this()

super和this的用法

关键字 成员变量 成员方法 构造方法
this() this.成员变量 访问本类成员变量 this.成员方法名() 访问本类成员方法 this(…) 访问本类构造方法
super() super.成员变量 访问父类成员变量 super.成员方法名() 访问父类成员变量 super(…) 访问父类构造方法

注意:

  • 子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。

  • super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。

  • super(…)和this(…)是根据参数去确定调用父类哪个构造方法的。

  • super(…)可以调用父类构造方法初始化继承自父类的成员变量的数据。

  • this(…)可以调用本类中的其他构造方法。

十.多态

概念:

多态是面向对象三大特征之一(封装,继承,多态)

多态是指同一行为,具有多个不同表现形式。

多态是出现在继承或者实现关系中的。

多态的前提

  1. 有继承或者实现关系

  2. 方法的重写【意义体现:不重写,无意义】

  3. 父类引用指向子类对象【格式体现】

格式

父类类型 变量名 = new 子类/实现类构造器;
变量名.方法名();

父类类型:指子类对象继承的父类类型,或者实现的父接口类型。

1.多态的使用

不用多态:

Java入门学习笔记_第19张图片

使用多态后,方法的形参就可以定义为共同的父类Person

Java入门学习笔记_第20张图片

注意:

  • 当一个方法的形参是一个类,我们可以传递这个类所有的子类对象。
  • 当一个方法的形参是一个接口,我们可以传递这个接口所有的实现类对象。
  • 多态还可以根据传递的不同对象来调用不同类中的方法。

2.多态的运行特点

调用成员变量时:编译看左边,运行看左边

调用成员方法时:编译看左边,运行看右边

Fu f = new Zi()//编译看左边的父类中有没有name这个属性,没有就报错
//在实际运行的时候,把父类name属性的值打印出来
System.out.println(f.name);
//编译看左边的父类中有没有show这个方法,没有就报错
//在实际运行的时候,运行的是子类中的show方法
f.show();

3.多态的弊端

多态编译阶段是看左边父类类型的,如果子类有些独有的功能,此时多态的写法就无法访问子类独有功能了

class Animal{
    public  void eat()System.out.println("动物吃东西!")}
class Cat extends Animal {  
    public void eat() {  
        System.out.println("吃鱼");  
    }  
   
    public void catchMouse() {  
        System.out.println("抓老鼠");  
    }  
}  

class Dog extends Animal {  
    public void eat() {  
        System.out.println("吃骨头");  
    }  
}

class Test{
    public static void main(String[] args){
        // 向上转型  
        Animal a = new Cat();
        a.eat();
        a.catchMouse();//编译报错,编译看左边,Animal没有这个方法
        
        //解决方案,向下转型  
        Cat c = (Cat)a;       
        c.catchMouse();
    }
}

4.引用类型转换

为什么转换呢?

就是为了解决多态的弊端:多态的写法无法访问子类独有功能

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有的,而父类没有的方法。那么想要调用子类特有的方法,必须做向下转型。

向上转型(自动转换)

**向上转型:**多态本身就是子类类型向父类类型向上转换的过程,这个过程是默认的。
当父类引用指向一个子类对象时,便是向上转型。
格式:

父类类型  变量名 = new 子类类型();
Animal a = new Cat();

**原因:父类类型相对与子类来说是大范围的类型,Animal是动物类,是父类类型。Cat是猫类,是子类类型。Animal类型的范围当然很大,包含一切动物。**所以子类范围小可以直接自动转型给父类类型的变量。

向下转型(强制转换)

向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。

格式:

子类类型 变量名 = (子类类型) 父类变量名;
Aniaml a = new Cat();
Cat c =(Cat) a;  

instanceof 关键字

为了避免运行时ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验

格式:

变量名 instanceof 数据类型 
    
如果变量属于该数据类型或者其子类类型,返回true。
如果变量不属于该数据类型或者其子类类型,返回false

在转换前,我们可以先做一个判断,如:

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        if (a instanceof Cat){
            Cat c = (Cat)a;       
            c.catchMouse();        // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
            Dog d = (Dog)a;       
            d.watchHouse();       // 调用的是 Dog 的 watchHouse
        }else{
            System.out.println("没有这个类型,无法转换");
        }
    }  
}

instanceof新特性:

JDK14的时候提出了新特性,把判断和强转合并成了一行

//新特性
//先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为d
//如果不是,则不强转,结果直接是false
if(a instanceof Dog d){
    d.lookHome();
}else if(a instanceof Cat c){
    c.catchMouse();
}else{
    System.out.println("没有这个类型,无法转换");
}

十一.抽象类

父类知道子类应该有哪个功能,但是功能具体怎么实现父类是不清楚(由子类自己决定),父类只需要提供一个没有方法体的定义即可,具体实现交给子类自己去实现。我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类

1.abstract关键字

用于修饰方法和类,修饰的方法是抽象方法,修饰的类是抽象类。

抽象方法

使用abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。

定义:

修饰符 abstract 返回值类型 方法名 (参数列表);

public abstract void run()

注意:抽象方法的类必须定义成抽象类

抽象类

如果一个类包含抽象方法,那么该类必须是抽象类。注意:抽象类不一定有抽象方法,但是有抽象方法的类必须定义成抽象类。

定义:

abstract class 类名字 { 
  
}

public abstract class Animal {
    public abstract void run()}

例:

// 父类,抽象类
abstract class Employee {
	private String id;
	private String name;
	private double salary;
	
	public Employee() {
	}
	
	public Employee(String id, String name, double salary) {
		this.id = id;
		this.name = name;
		this.salary = salary;
	}
	
	// 抽象方法
	// 抽象方法必须要放在抽象类中
	abstract public void work();
}

// 定义一个子类继承抽象类
class Manager extends Employee {
	public Manager() {
	}
	public Manager(String id, String name, double salary) {
		super(id, name, salary);
	}
	// 2.重写父类的抽象方法
	@Override
	public void work() {
		System.out.println("管理其他人");
	}
}

// 定义一个子类继承抽象类
class Cook extends Employee {
	public Cook() {
	}
	public Cook(String id, String name, double salary) {
		super(id, name, salary);
	}
	@Override
	public void work() {
		System.out.println("圣美要快点找个女朋友哈!!!");
	}
}

// 测试类
public class Demo10 {
	public static void main(String[] args) {
		// 创建抽象类,抽象类不能创建对象
		// 假设抽象类让我们创建对象,里面的抽象方法没有方法体,无法执行.所以不让我们创建对象
//		Employee e = new Employee();
//		e.work();
		
		// 3.创建子类
		Manager m = new Manager();
		m.work();
		
		Cook c = new Cook("002", "圣美", 1);
		c.work();
	}
}

此时的方法重写,是子类对父类抽象方法的完成实现,也叫做实现方法

2.注意事项

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

  2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。

  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通过而报错。

  5. 抽象类存在的意义是为了被子类继承。

十二.接口

接口是更加彻底的抽象,JDK7之前,包括JDK7,接口中全部是抽象方法和常量。接口也是不能创建对象的。

定义:

//接口的定义格式:
interface 接口名称{
    // 抽象方法
}

// 接口名称:首字母大写,满足“驼峰模式”

抽象方法:

接口中的抽象方法默认会自动加上public abstract修饰,可以不写

常量:

在接口中定义的成员变量默认会加上 public static final修饰。也就是说在接口中定义的成员变量实际上是一个常量。这里是使用public static final修饰后,变量值就不可被修改,并且是静态化的变量可以直接用接口名访问,所以也叫常量。常量必须要给初始值

public interface InterF {
    // 抽象方法!
    //    public abstract void run();
    void run();

    //    public abstract String getName();
    String getName();

    //    public abstract int add(int a , int b);
    int add(int a , int b);


    // public static final int AGE = 10 ;
    int AGE  = 10; //常量
    String SCHOOL_NAME = "黑马大学";

}

类与接口的实现

类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements关键字。

格式:

/**接口的实现:
    在Java中接口是被实现的,实现接口的类称为实现类。
    实现类的格式:*/
class 类名 implements 接口1,接口2,接口3...{

}

要求:

  1. 必须重写实现的全部接口中所有抽象方法。
  2. 如果一个类实现了接口,但是没有重写完全部接口的全部抽象方法,这个类也必须定义成抽象类。

意义:

接口体现的是一种规范,接口对实现类是一种强制性的约束,要么全部完成接口申明的功能,要么自己也定义成抽象类。这正是一种强制性的规范。

定义一个人的接口,如:

public interface PlayMan {
    void run(); // 抽象方法,跑。
    void eat(); // 抽象方法,吃。
    String playgame(String game);  // 抽象方法,打游戏
}

接下来定义一个"我"的类,实现接口,实现接口的实现类代码如下:

/**
 * 接口的实现:
 *    在Java中接口是被实现的,实现接口的类称为实现类。
 *    实现类的格式:
 *      class 类名 implements 接口1,接口2,接口3...{
 *
 *
 *      }
 * */
public class Mankind  implements PlayMan {
    @Override
    public void run() {
        System.out.println("圣美跑不动了");
    }

    @Override
    public void eat() {
        System.out.println("圣美想吃零食!!");
    }

    @Override
    public String playgame(String game) {
        return "圣美在玩"+game;
    }
}

测试代码:

public class TestMain {
    public static void main(String[] args) {
        // 创建实现类对象。
        Mankind m = new Mankind();
        m.run();
        m.eat();
        System.out.println(m.playgame("王者荣耀"));

    }
}

类与接口的多实现:

类与接口之间的关系是多实现的,一个类可以同时实现多个接口。

定义两个接口,如:

public interface Eat {
    void eat();
}

public interface Run {
    void run();
}

然后定义一个实现类:

/**
 * Java中接口是可以被多实现的:
 *    一个类可以实现多个接口: Eat, Run
 * */
public class Mankind implements Eat ,Run {
    @Override
    public void eat() {
        System.out.println("圣美想吃零食");
    }

    @Override
    public void run() {
        System.out.println("圣美跑不动了!");
    }
}

接口与接口的继承

Java中,接口与接口之间是可以多继承的:也就是一个接口可以同时继承多个接口。

接口继承接口就是把其他接口的抽象方法与本接口进行了合并。

如:

public interface Abc {
    void go();
    void test();
}

public interface Law {
    void rule();
    void test();
}


public interface SportMan extends Law , Abc {
    void run();
}

十三.内部类

概念:

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。可以把内部类理解成寄生,外部类理解成宿主。

分类 类的位置
成员内部类 类定义在了成员位置 (类中方法外称为成员位置,无static修饰的内部类)
静态内部类 类定义在了成员位置 (类中方法外称为成员位置,有static修饰的内部类)
局部内部类 类定义在方法内
匿名内部类 没有名字的内部类,可以在方法中,也可以在类中方法外

1.成员内部类

无static修饰的内部类,属于外部类对象的。

格式:

 外部类.内部类。 // 访问内部类的类型都是用 外部类.内部类

获取成员内部类对象的两种方式:

方式一:外部直接创建成员内部类的对象

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

方式二:在外部类中定义一个方法提供内部类的对象

例:

方式一:
public class Test {
    public static void main(String[] args) {
        //  宿主:外部类对象。
       // Outer out = new Outer();
        // 创建内部类对象。
        Outer.Inner oi = new Outer().new Inner();
        oi.method();
    }
}

class Outer {
    // 成员内部类,属于外部类对象的。
    // 拓展:成员内部类不能定义静态成员。
    public class Inner{
        // 这里面的东西与类是完全一样的。
        public void method(){
            System.out.println("内部类中的方法被调用了");
        }
    }
}


方式二:
public class Outer {
    String name;
    private class Inner{
        static int a = 10;
    }
    public Inner getInstance(){
        return new Inner();
    }
}

public class Test {
    public static void main(String[] args) {
        Outer o = new Outer();
        System.out.println(o.getInstance());


    }
}

注意:

  1. 成员内部类可以被一些修饰符所修饰,比如: private,默认,protected,public,static等
  2. 在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量。
  3. 创建内部类对象时,对象中有一个隐含的Outer.this记录外部类对象的地址值。

2.静态内部类

  • 静态内部类是一种特殊的成员内部类。
  • 有static修饰,属于外部类本身的。
  • 静态内部类与其他类的用法完全一样,只是访问的时候需要加上外部类.内部类
  • 拓展1:静态内部类可以直接访问外部类的静态成员。
  • 拓展2:静态内部类不可以直接访问外部类的非静态成员,如果要访问需要创建外部类的对象。
  • 拓展3:静态内部类中没有隐含的Outer.this。

格式:

外部类.内部类。

静态内部类创建对象的格式:

外部类.内部类  变量 = new  外部类.内部类构造器;

调用方法的格式:

//调用非静态方法的格式:
先创建对象.用对象调用;

//调用静态方法的格式:
外部类名.内部类名.方法名();

例:

// 外部类:Outer01
class Outer01{
    private static  String sc_name = "黑马";
    // 内部类: Inner01
    public static class Inner01{
        // 这里面的东西与类是完全一样的。
        private String name;
        public Inner01(String name) {
            this.name = name;
        }
        public void showName(){
            System.out.println(this.name);
            // 拓展:静态内部类可以直接访问外部类的静态成员。
            System.out.println(sc_name);
        }
    }
}

public class InnerClassDemo01 {
    public static void main(String[] args) {
        // 创建静态内部类对象。
        // 外部类.内部类  变量 = new  外部类.内部类构造器;
        Outer01.Inner01 in  = new Outer01.Inner01("圣美");
        in.showName();
    }
}

3.局部内部类

定义在方法中的类

格式:

class 外部类名 {
	数据类型 变量名;
	
	修饰符 返回值类型 方法名(参数列表) {
		// …
		class 内部类 {
			// 成员变量
			// 成员方法
		}
	}
}

4.匿名内部类

匿名内部类是内部类的简化写法。他是一个隐藏了名字的内部类。

格式:

new 类名或者接口名() {
     重写方法;
};

包含了:

  • 继承或者实现关系

  • 方法重写

  • 创建对象

所以从语法上来讲,这个整体其实是匿名内部类的对象

如果我们希望定义一个只要使用一次的类,就可考虑使用匿名内部类。匿名内部类的本质作用:是为了简化代码。

之前我们使用接口时:

  1. 定义子类
  2. 重写接口中的方法
  3. 创建子类对象
  4. 调用重写后的方法
interface Swim {
    public abstract void swimming();
}

// 1. 定义接口的实现类
class Student implements Swim {
    // 2. 重写抽象方法
    @Override
    public void swimming() {
        System.out.println("潜泳式...");
    }
}

public class Test {
    public static void main(String[] args) {
        // 3. 创建实现类对象
        Student s = new Student();
        // 4. 调用方法
        s.swimming();
    }
}

匿名内部类前提:

必须继承一个父类或者实现一个父接口

格式:

new 父类名或者接口名(){
    // 方法重写
    @Override 
    public void method() {
        // 执行语句
    }
};

例:

interface Swim {
    public abstract void swimming();
}

public class Demo03 {
    public static void main(String[] args) {
        // 使用匿名内部类
		new Swim() {
			@Override
			public void swimming() {
				System.out.println("自由泳...");
			}
		}.swimming();

        // 接口 变量 = new 实现类(); // 多态,走子类的重写方法
        Swim s2 = new Swim() {
            @Override
            public void swimming() {
                System.out.println("潜泳式...");
            }
        };

        s2.swimming();
        s2.swimming();
    }
}

扩展:

通常在方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递。如:

interface Swim {
    public abstract void swimming();
}

public class Demo03 {
    public static void main(String[] args) {
        // 普通方式传入对象
        // 创建实现类对象
        Student s = new Student();
        
        goSwimming(s);
        // 匿名内部类使用场景:作为方法参数传递
        Swim s3 = new Swim() {
            @Override
            public void swimming() {
                System.out.println("蝶泳...");
            }
        };
        // 传入匿名内部类
        goSwimming(s3);

        // 完美方案: 一步到位
        goSwimming(new Swim() {
            public void swimming() {
                System.out.println("大学生, 潜泳...");
            }
        });

        goSwimming(new Swim() {
            public void swimming() {
                System.out.println("小学生, 自由泳...");
            }
        });
    }

    // 定义一个方法,模拟请一些人去游泳
    public static void goSwimming(Swim s) {
        s.swimming();
    }
}

希望我的笔记对你们有帮助,我喜欢你们的点赞,感谢、感谢!!!

你可能感兴趣的:(java,java)