【Java】Java 基础知识(一)语法

文章目录


一、常用的DOS命令

操作说明
盘符名称:+回车盘符切换;如 E:+回车(表示切换到E盘)
dir查看当前路径下的内容
mkdir新建文件夹
rmdir删除文件夹
cd目录进入单级目录,如cd java+进入Java目录
cd…回退到上一级目录
cd 目录1\目录2…进入多级目录,如cd itheima\javaSE
cd\回到盘符目录
cls清屏
exit退出命令提示窗口

二、安装开发环境

1.JDK——搭建Java开发环境

1.1 概述

1.1.1 JDK、JRE和JVM

(1) JRE——Java Tuntime Environment,是Java的运行时环境,包含JVM和运行时所需要的核心类库;

(2) JVM:Java虚拟机,实现Java语言跨平台,但JVM本身是不跨平台的;

(3) JDK:全称Java Development kit 是Java程序开发工具包,是整个Java的开发的核心;(想要开发一个全新的Java程序,必须安装JDK)

(4) JDK、JRE和JVM的关系图:

JDK、JRE和JVM关系图

1.2 JDK的下载与安装

1.2.1 JDK 的下载:

(1) 直接从JDK的官网下载 http://www.oracle.com

(2) 注意:

        ① 针对不同操作系统,下载对应的JDK;
        ② 安装时,路径中不要包含中文和空格,所有的开发工具最好安装目录统一;

1.2.2 JDK的安装目录详解:
目录名称说明
bin该路径下存放了JDK的各种工具命令,Javac和Java就放在这个目录
conf该路径下存放了JDK的相关配置文件
include该路径下存放了一些平台特定的头文件
jmods该路径下存放了JDK的各种模块
legal该路径下存放了JDK各模块的授权文档
lib该路径下存放了JDK工具的一些补充AR包
  • 其余文件为说明性文档;
1.2.3 JDK安装:

(1) 先查询有没有安装过JDK;
        ① Win+R→cmd→回车;
        ② 输入java -version→回车;

(2) 下载JDK软件,双击安装;

(3) 一个电脑可以安装多个JDK软件;

(4) 安装完JDK以后要配置环境变量,配置哪个,哪个生效;

(5) 去相应文件夹底下查看是否安装成功;

(6) 安装完JDK以后,进行环境变量的配置(配置环境变量是为了让电脑找到刚安装好的JDK)
        ① 右键(我的电脑)→属性→高级系统设置→环境变量→对话框→系统变量;
        ② 新建:

变量名JAVA_HOME
变量值JDK安装路径(c:\Program\Java\JDK)

        ③ 修改系统变量的Path(bin目录):找Path→编辑→新建→将JDK的路径中bin文件夹的路径放入Path里面,不许删其他东西;
        ④ 新建系统变量 CLASS_PATH

变量名CLASS_PATH
变量值c:\Program\Java\jdk1.8.01\lib;

        ⑤ JDK配置完成后测试一下是否安装成功:Win+R→cmd回车→java -version 回车。
        ⑥ (网上搜步骤)在Eclipse安装完成之后,需要给Eclipse配置JDK;
        ⑦ 配置完上面的之后,再下载配置Maven;
            ● 电脑→右键→高级系统设置→环境变量→新建系统变量:

变量名MAVEN_HOME
变量值MAVEN安装的根目录

            ● 在Path中新建:%MAVEN_HOME%\bin
            ● 验证是否成功:Win+R→cmd 回车→输入 mvn -v
            ● 镜像;
            ● 修改Maven仓库的默认位置;
            ● 在编辑器(IDEA或Eclipse)上配置Maven工具;

2.Eclipse

2.1 概述

    ● Eclipse是一个开放源代码,基于Java的可扩展的开发平台;

2.2 Eclipse下载与安装

2.3 Eclipse的工作空间workspace

    ● 系统生成的都不要动;
    ● 右键→Run As→JavaApplication→运行代码

3.IDEA

3.1 概述


三、Java小知识

1.HelloWorld案例

1.1 工程项目→模块→包→类

1.2 使用Eclipse开发工具:

      ① File→New→Other…(快捷键 Ctrl+N,说明:设置开发版本JavaSE/EE/ME)
      ② File→New→Java Project (说明:创建工程项目)
           Project name→工程项目名称→Finish(完成)
      ③ 创建包(包名全小写)
          ● 右键→New→Package
          ● 包名举例 com.aabb.cc(公司的域名倒着写)
      ④ 创建HelloWorld类(类名要符合驼峰命名法,如HelloWorld.java)
      ⑤ 编写代码:

package com.aabb.cc;  // 声明包
public class HelloWorld{  // 定义了一个类,类名HelloWorld
    public static void main(String[] args){  // main方法,格式是固定的
        System.out.println("Hello World!!");  // 输出语句 Hello World!!
    }
}

          ★ 注意:main方法为主方法,是程序的入口;程序的执行从main开始,main结束则程序结束;

2.编译和运行

编译: javac 文件名.java例:javac HelloWorld.java
执行:Java 类名例:java HelloWorld

3.Java程序中最基本的组成单位是类

    ● 类的定义格式: public class 类名{}

4.说明/注释

(1) 注释:是在程序指定位置添加的说明性信息,不参与程序运行;

(2) 注释分类:
      ● 单行注释: // 注释信息
      ● 多行注释: /* 注释信息 /
      ● 文档注释: /
** 注释信息 */

5.运行与工作原理

Java运行工作与原理
(1) 编译:通过Javac命令,将Java的源文件,也就是.java文件编译成.class文件;

(2) 执行:先启动Java虚拟机,不同的操作系统有不同的JVM,因此Java跨平台;再通过JVM加载HelloWorld.class字节码文件,并加载main方法执行程序;

6.计算机存储单元

(1) 计算机设备的最小信息单元叫“为(bit)”,用小写字母“b”表示;

(2) 计算机中最小的存储单元叫“字节(byte)”,用大写字母“B”表示;

  • 1 byte = 8 bit
  • 1 KB = 1024B

四、Java 语言基础

1.变量与数据类型

1.1 标识符

1.1.1 标识符定义:就是给类、方法、变量等起名字的符号;
1.1.2 标识符定义规则:
  • 标识符可以由字母、数字、下划线(_)、美元符号($)组成,但不能包含@、%、空格等特殊符号;
  • 不能以数字开头;
  • 标识符是严格区分大小写的;
  • 标识符的命名最好能反映其作用,做到见名知意;
1.1.3 标识符常见命名:

(1) 小驼峰命名法:
      ① 一个单词的时候,首字母小写,如:name;
      ② 多个单词组成的时候,首个单词的首个字母小写,其他单词首字母大写,如:firstName;

(2) 大驼峰命名法:
      ① 一个单词时,首字母大写,如:Student;
      ② 多个单词时,首字母大写,如:GoodStudent;

(3) 小驼峰命名法是针对方法和变量的命名;大驼峰命名法是针对类的命名;

1.2 关键字

1.2.1 关键字是指被Java语言赋予了特定含义的单词,关键字不能被用作标识符;
1.2.2 现在一共有53个关键字,其中有两个保留字:const和goto;
abstractbooleanbreakbytecasecatch
charclasscontinuedefaultdodouble
elseextendsfalsefinalfinallyfloat
forifimplementsimportinstanceofint
interfacelongnativenewnullpackage
privateprotectedpublicreturnshortstatic
superswitchsynchronizedthisthrowthrows
transienttruetryvoidvolatilewhile
1.2.3 ★ 关键字的字母全部大小写,常用的代码编辑器,针对关键字有特殊的颜色标记,很直观;

1.3 变量

(1) 变量定义:指在内存中开辟的存储空间,用于存放运算过程中需要用到的数据;即:在程序运行过程中,其值可以发生改变的量;

  • 变量有三个元素:数据类型、变量名和变量值;
  • 变量用来记录,程序中可以变的值;
  • 变量出现的位置不同,名字特点,作用都不同;
  • 出现在成员位置(类里方法外)的变量,叫做成员变量;
  • 出现在局部位置(方法里)的变量,叫做局部变量;

(2) 变量定义格式: 数据类型 变量名 = 变量值;

  • 例: int a = 10; // 声明int类型的变量a,并赋值为10;
  • 例: String tel; // 声明String类型的变量tel;

(3) 变量初始化指的是第一次赋值;

(4) 变量主要用于取值和修改值;
      ① 取值格式: 变量名 例:a
      ② 变量名 = 变量值; 例:a = 20;

(5) 变量使用的注意事项:
      ① 变量名必须是一个有效的标识符;
      ② 变量名不可以使用Java关键字;
      ③ 变量名不能重复;
      ④ 变量未赋值,不能使用;
      ⑤ long 类型的变量定义的时候,为了防止整数过大,后面要加L;
      ⑥ float 类型的变量定义的时候,为了防止类型不兼容,后面要加F;

(6) 局部变量:定义在方法里,或者局部代码块中的变量;

  • 注意:必须手动初始化,未分配内存,如: int i = 5;
  • 作用域也就是方法里或者局部代码块里,方法运行完内存就释放了;

(7) 成员变量:定义在类里;

  • 注意:不用初始化,也会自动被初始化成默认值;
  • 作用域是整个类中,类消失了,变量才释放;

(8) 测试变量:

package com.java.test;

import org.junit.jupiter.api.Test;

// 测试 变量
public class Test6{
	// 1.成员变量:位置是在类里方法外+整个类中都有效+有默认值(类型不同值不同)
	String name;  // 引用类型的 默认值是null
	int sex;  // 默认值是0
	double score;  // 默认值是0.0
	boolean flag;  // 默认值是 false
	char a;  // 默认值是 \u0000
	int age;
}

@Test
public void show(){
	// 2.局部变量是在方法里+只在方法里有效+没有默认值必须赋值(初始化)
	int age = 10;
	// 4.当成员变量和局部变量同名时,就近原则,优先使用局部变量,10
	System.out.println(age);  // 使用局部变量,10
	System.out.println(name);  // 成员变量,null
	System.out.println(sex);  // 成员变量,0
	System.out.println(score);  // 成员变量,0.0
	System.out.println(flag);  // 成员变量,false
	System.out.println(a);  // 成员变量,\u0000

	// 3.flag的默认值是false,取反得true使判断条件成立
	if(!flag){
		System.out.println(1);
	}
}

(9) 成员变量和局部变量

      ① 成员变量:在class类里面,但在方法外面的变量;

      ② 局部变量:在方法里面的变量叫局部变量;

      ③ 成员变量和局部变量区别:

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

(10) 静态变量和实例变量的区别

      ① 在语法定义上的区别:静态变量前要加static关键字,而实例变量前不加;

      ② 在程序运行时的区别:

  • 实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量;
  • 静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会分配空间,静态变量就可以被使用了;
  • 总之:实例变量必须创建对象后才可以通过这个对象来使用;静态变量则可以直接使用类名来引用;

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

1.4 常量

(1) 常量定义:在程序运行过程中,其值不会发生改变的量;

(2) 常量分类:

常量类型说明举例
字符串常量用双引号括起来的内容“HelloWorld” “橘子”
整数常量不带小数的数字666 -22
小数常量带小数的数字13.12 -5.33
字符常量用单引号括起来的内容‘A’ ‘我’
布尔常量布尔值,表示真假只有两个值 true false
空常量一个特殊的值,空值值是 null (空常量是不能直接输出的)

1.5 数据类型

数据类型

1.5.1 基本数据类型(八种)

(1) 基本数据类型的内存占用和取值范围:

数据类型关键字内存占用取值范围
整数byte1个字节-128~127
short2个字节-32768~32767
int(默认)4个字节-2^31~2^31-1
long8个字节-2^63~2^63-1
浮点数float4个字节1.401298e^-45~3.402823e^38
double(默认)8个字节4.9000000e~1.797693e^38
字符char2个字节0~65535
布尔boolean1个字节true(1), false(0)
  • e+38 表示乘以10的38次方;
  • e-45 表示乘以10的负45次方;

(2) 基本类型的字面值
      ① 整数字面值是int类型;
      ② byte,short,char三种比int小的整数可以用范围内的值直接赋值;
      ③ 浮点数的字面值是double类型;
      ④ 字面值后缀:L-long,F-float,D-double;
      ⑤ 进制前缀:0x - 16进制;0 - 8进制; \u - char类型,16进制;

(3) 基本类型的类型转换:分为自动类型转换和强制类型转换;

      ① 自动类型转换(小到大,属于隐式转换)—— 把一个表示数据范围小的数值或者变量赋值给另一个表示数据范围大的变量;

        如:double d = 10; (10是int类型)

自动类型转换
      ② 强制类型转换(大到小——显示转换)

  • 强制类型转换——把一个表示数据范围大的数值或者变量赋值给另一个表示数据范围小的变量;
  • 格式: 目标数据类型 变量名 = (目标数据类型)值或者变量;
  • 例:
// 范围大 → 范围小(float转成int)
float a = 88.8;
int k = (int) 88.88;
1.5.2 引用类型

(1) 引用类型是一个对象类型,它的值是指向内存空间的引用,就是地址,所指向的内存中保存着变量所表示的一个值或一组值,如类、接口、数组;

============================================

2.运算符与表达式

2.1 运算符概述

(1) 运算符是一种特殊的符号,主要用于数学函数,一些类型的赋值语句和逻辑比较方面,对常量或者变量进行操作的符号;

(2) Java 的运算符有算术运算符、比较运算符、逻辑运算符、三元运算符、赋值运算符;

(3) 表达式:用运算符把常量或者变量连接起来符合Java语法的式子就可以称为表达式;(不同运算符连接的表达式体现的是不同类型的表达式)

(4) 范例:

int a = 10;
int b = 20;
int c = a + b;
  • + 是运算符,而且是算术运算符;
  • a+b:是表达式,而且是算术表达式(因为是用“+”号运算的)

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.2 算术运算符

(1) Java中的算术运算符主要有+(加)、-(减)、*(乘)、/(除)、%(取余)它们都是二元运算符;

(2) 算术运算符

符号作用说明
+
-
*
/取结果的商
%取余获取的是两个数据做除法的余数

注意:整数与整数运算符只会得到整数,要想有小数,必须有浮点数参与运算;0不能作除数,否则系统会抛出异常ArithmeticException;

(3) 字符的“+”操作
      ① 拿字符在计算机底层对应的数值来进行计算的;

‘A’ → 65A → Z 是连续的
‘a’ → 97a → z 是连续的
‘0’ → 480 → 9 是连续的
  • 算术表达式中包含多个基本数据类型的值的时候,整个算术表达式的类型会自动进行提升;
  • byte 类型、short 类型和char 类型将被提升到 int 类型;
  • 整个表达式的类型自动提升到表达式中最高等级操作数同样的类型;等级顺序是:byte,short,char → int → long → float → double;

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.3 赋值运算符 =

(1) 赋值运算符以符号“=”表示,它是一个二元运算符(对两个操作数作处理),其作用是将右方操作数所含的值赋给左方的操作数;
例如:

a = 10;  // 将10赋值给变量a
int i = 10;  // 把10赋值给int类型的变量 i

(2) += (把左边和右边的数据做加法,再将其结果赋值给左边)

例: i + = 20 相当于 i = i + 20;

  • += 隐含了强制类型转换;

(3)所有赋值运算符

符号作用说明
=赋值a=10(将10赋值给变量a)
+=加后赋值a+=b(将a+b的值赋值给a)
-=减后赋值a-=b(将a-b的值赋值给a)
*=乘后赋值a*=b(将a*b的值赋值给a)
/=除后赋值a/=b(将a/b的值赋值给a)
%=取余后赋值a%=b(将a/b的余数赋值给a)
  • 注意:(+=,-=,*=,/=,%= 隐含了强制类型转换)

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.4 自增和自减运算符

(1) 自增、自减运算符是单目运算符,可以放在操作元(++ i)之前,也可以放在操作元(++ i)之后;

(2) 操作元必须是一个整型或浮点型变量;

(3) 自增、自减的作用是使变量的值赠1或减1;

(4) 放在操作元(++ i)前面的自增、自减运算,会先将变量的值加1(或减1),然后再使该变量参与表达式的运算;

  • 放在操作元(++ i)后面的自增、自减运算符,会先使变量参与表达式的运算,然后再将该变量加1(减1)
代码结果解析
int j = i++j = i , i = i + 1++在变量后面时,先把变量i的值赋值给 j ,然后变量 i 本身再做 ++ (即 i+1)
int j = ++ii = i + 1 , j = i +1当++在变量前面时,先做++的操作(即i+1),再操作之后的结果赋值给 j

(5) ++a 与 a++ 的作用都相当于 a=a+1;

(6) 所有自增、自减运算符:

符号作用说明
++自增变量的值加1
自减变量的值减1

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.5 比较运算符/关系运算符(结果是boolean)

(1) 比较运算符主要用于程序中的变量之间,变量和自变量之间以及其他类型的信息之间的比较,属于二元运算符;

(2) 比较运算符的运算结果是boolean型(即 true/false)

(3) 比较运算符

符号作用操作数据举例
>比较左方是否大于右方整型,浮点型,字符型‘a’ > ‘b’ → false
<比较左方是否小于右方整型,浮点型,字符型156 < 456 → true
==比较左方是否等于右方基本数据类型,引用型‘c’ == ‘c’ → true
>=比较左方是否大于等于右方整型,浮点型,字符型479 >= 426 → true
<=比较左方是否小于等于右方整型,浮点型,字符型12.45 <= 45.5 → true
!=比较左方是否不等于右方基本数据类型,引用型‘y’ != ‘t’ → true

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.6 逻辑运算符

(1) 逻辑运算符定义:一个返回类型为布尔值的表达式(比如比较运算符),可以被组合在一起构成一个更复杂的表达式,这个复杂的表达式需要通过逻辑运算符来实现;

(2) 所有逻辑运算符

符号作用说明
&逻辑与a & b,表达式a和b都是true,结果为true,否则为false
|逻辑或a | b,表达式a和b都是false,结果为false,否则为true
^逻辑异或a^b,表达式a和b结果不同为true,相同为false
!逻辑非!a,结果和a的结果相反

(3) 短路逻辑运算符

符号作用说明
&&短路与作用和&相同,但是有短路效果
||短路或作用和 | 相同,但是有短路效果

注意事项:

      ① 逻辑与(&),无论左边真假,右边都要执行;

          短路与(&&),如果左边为真(true),右边执行;如果左边为假(false),右边不执行;

      ② 逻辑或(|),无论左边真假,右边都要执行;

          短路或(||),如果左边为假(false),右边执行;如果左边为真(true),右边不执行;

      ③ 最常用的逻辑运算符 &&(短路与),||(短路或),!(逻辑非)

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.6 三元运算符

(1) 三元运算符格式:

三元运算符关系表达式 ? 表达式1 : 表达式2
范例a>b ? a : b

解析: 若关系表达式的值为true,则表达式1的值就是运算结果;否则,表达式2的值就是运算结果;

(2) 范例:输出两个值中的最大值(三元运算符)

package com.java.basic;

import java.util.Scanner;

/** 需求:本类用于接收用户输入的两个值,并把最大值输出 */
public class TestMaxNum{
	// 1.创建程序的入口函数main()
	public static void main(String[] args){
		// 2.提示并接收用户输入的两个整数
		System.out.println("请输入您要比较的第一个数:");
		int a = new Scanner(System.in)nextInt();
		System.out.println("请输入您要比较的第二个数:");
		int b = new Scanner(System.in)nextInt();
		
		// 3.比较用户输入的这两个数
		/** 三元运算符:1 ? 2:3
		* 1 是表达式,如果1的结果为true,结果取2号位置的值
		* 如果1的结果为false,结果取3号位置的值;
		**/

		// 4.定义变量max来保存最大值
		// a>b 这是一个表达式,如果a大于b,表达式的结果是true,反之是false;
		int max = a>b ? a : b;

		/** 作业1:求两个数的最小值 */
		/** 作业2:求三个数的最大值 */
		// 5.打印比较的结果
		System.out.println("两个数的最大值:" + max);
	}
}

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.7 运算符的优先级

(1) 运算符优先级由高到低的顺序依次是:

自增自减运算 → 算数运算 → 比较运算 → 逻辑运算 → 赋值运算;

(2) 运算符的优先级

优先级描述运算符
1括号()
2正负号+,-
3一元运算符++,–,!
4乘除*,/,%
5加减+,-
6移位运算符>>,>>>,<<
7比较大小<,>,>=,<=
8比较是否相等==,!=
9按位与运算&
10按位异或运算^
11按位或运算|
12逻辑与运算&&
13逻辑或运算||
14三元运算符? :
15赋值运算符=

============================================

3.流程控制语句

流程控制语句分类顺序结构
分支结构(if 语句,switch 语句)
循环结构(for 循环; while 循环;do...while循环)

3.1 顺序结构

(1) 顺序结构定义:按照代码的先后顺序,依次执行;

(2) 开始 → 语句A → 语句B → 语句C → 结束;

3.2 条件语句/分支语句(用来解决先判断,再执行的问题)

3.2.1 if 条件语句

(1) if 条件语句概述:先做判断(true/false),再执行问题;

(2) 形式
      ① if 单分支语句:

单分支
      ② if 多分支语句:

多分支
      ③ if 嵌套分支语句:

if(判断条件1){
	语句体1;
} else if (判断条件2){
	语句体2;
} else if (判断条件3){
	语句体3;
} else {
	语句体4;
}

if 嵌套分支语句执行流程:

  • 首先计算关系表达式1的值(true/false);
  • 如果值为true,就执行语句体1,;如果值为false就计算关系表达式2的值(true/false);
  • 如果值为true,就执行语句体2,如果值为false就计算关系表达式3的值;
  • ……
  • 如果没有任何关系表达式为true,就执行语句体4;

(3) 案例1:(if 嵌套分支结构)需求:接收用户输入的原作,满1000打9折,满2000打8折,满5000打5折;

package com.java.basic;

import java.util.Scanner;

// 测试 分支结构
// 接收用户输入的原价,满1000打9折,满2000打8折,满5000打5折;
public class Test{
	public static void main(String[] args){
		// 1.接收用户输入的原价
		double price = new Scanner(System.in).nextDouble();
		// dazhe(price);  // 调用方法,计算折后价 V1.0
		double x = dazhe(price);  // 调用方法,计算折后价 V2.0
		System.out.println("原价是" + price + ",折后价是" +x);
	}
	
	// 计算折后价
	// public static void dazhe(double a){  // V1.0
	public static double dazhe(double a){  // V2.0
		// 1.定义变量,记录折后价
		double b = 0;
		if(a >= 5000){  // a 满5000打5折
			b = a*0.5;  // a 打5折;
		} else if(a >= 2000){  // 满2000打8折
			b = a*0.8;  // a 打8折;
		} else if(a >= 1000){
			b = a*0.9;  // a打9折;
		}else{  // 不打折
			b = a;
		}
		return b;  // 通过return关键字把结果返回给调用位置;
		// System.out.println("原价是1000,折后价是900");
		// 动态数据在中间位置 “+?+”
		// System.out.println("原价是" +a+ ",折后价是" +b);
	}
}
3.2.2 switch 多分支语句:

(1) switch 多分支语句概述:当一个case成立,从这个case向后穿透所有case,包括default,直到程序结束或者遇到break程序才结束;

(2) switch 语句格式及执行流程

      ① switch 语句格式

switch(判断条件){
	case1:语句体1;
		break;
	case2:语句体2;
		break;
	...
	default: 语句体 n+1;
		[break;]
}

      ② switch 执行流程:

  • 首先判断条件(true/false);
  • 依次和case后面的值进行比较,如果有对应的值,就会执行相应的语句,在执行过程中,遇到break就会结束;
  • 如果所有的case后面的值和表达式的值都不匹配,就会执行default里面的语句体,然后程序就会结束掉;

(3) case具有穿透性:
      ① 说明:

  • 表达式:取值为 byte,short,int,char;JDK5以后可以是枚举;JDK7以后可以是String;
  • case:后面跟的是要和“判断条件”进行比较的值;
  • break:表示中断,结束的意思,用来结束switch语句;
  • default:表示所有情况,都不匹配的时候,就执行该处的内容,和if语句的else的相似;

(4) switch 语句执行流程图:

switch语句

(5) switch 语句案例:数字匹配

package com.java.test;

// 测试 分支结构
public class Test3{
	public static void main(String[] args){
		// 1.判断条件,只支持int,byte,short,char,String 类型的数据
		int a = 200;
		switch(a){
			case 0:System.out.println(0);break;
			case 1:System.out.println(1);break;
			// 2.当成功匹配到了case之后,要向穿透所有的case
			case 2:System.out.println(2);break; // 4.立刻结束
			case 3:System.out.println(3);break;
			case 4:System.out.println(4);break;
			// 3.default 是无论什么时候都会执行(如果没遇到break的话)
			default : System.out.println(100);
		}
	}
}

注意:数据测试时要做到正确数据、边界数据、错误数据都过关才合格;

3.3 循环语句

3.3.1 概述:
  • 循环语句用来解决需要反复执行某一操作的需求;有三种循环结构:for/while/do…while;
3.3.2 for 循环语句

(1) for 循环格式(中间用分号“;”隔开):

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

(2) 举例:在控制台输出 1-5 的数字;

for (int i=1;i<=5;i++){
System.out.println(i);
}

(3) for 循环执行流程

for 循环执行流程
(4) for 循环案例1:求[1,100] 里偶数的和

package com.java.test;

// 求[1,100] 里偶数的和
public class Test4{
	public static void main(String[] args){
		method();
	}

	public static void method(){
		int sum = 0;  // 1.定义变量,记录总和;
		// 2.获取 1~100 里的每个数字
		for(int i=1;i<=100;i++){
			if(i%2 == 0){  // 3.过滤偶数
				sum = sum + i;  // 4.求和:原来的值+新的值;
			}
		}
		System.out.println("偶数的总和是:" + sum);
	}
}

(5) 嵌套 for 循环:
      ① 概述:根据外层的条件,判断里层能否执行,如果能执行,就把里层代码都循环完毕后,再继续执行外层,继续判断(常用于各种算法的实现,还可以打印各种图形);

      ② 嵌套 for循环语法格式:

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

      ③ 嵌套 for循环特点:

  • 外循环,执行一次,内循环执行N次;
  • 外循环控制“行”,内循环控制“列”;

      ④ 嵌套 for循环案例:打印5行5列的*

package com.java.test;

// 测试 嵌套 for 循环;
public class Test1{
	public static void main(String[] args){
		// method();  // 1.外循环,执行1次,内循环执行N次;
		// method2();  // 2.外循环控制“行”,内循环控制“列”;
		method3();  // 3.练习:打印5行5列的*
	}

	// 3.练习:打印5行5列的*
	public static void method3(){
		for(int i=1;i<=5;i++){ // 外循环控制行,执行5次
			for(int j=1;j<=5;j++){  // 内循环控制列,执行5次
				System.out.print("*");  // 同行展示
			}
			System.out.println();  // 换行;
		}
	}

	// 当 i=1时,满足了 i<=2的判断条件,执行了第三大步,同一行展示了*****,换行
	// 当 i=2时,满足了 i<=2的判断条件,执行了第三大步,同一行展示了*****,换行
	// 2,外循环控制行,内循环控制列
	public static void method2(){
		for(int i=1;i<=2;i++){  // 外循环执行2次
			for(int j=1;j<=5;j++){  // 内循环执行5次
				System.out.print("*"); // 同一行
			}
			System.out.println();  // 换行
		}
	}

	// 当 i=1时,满足了 i<4的判断条件,执行了第三大步,输出了i的值1,j的值12345;
	// 当 i=2时,满足了 i<4的判断条件,执行了第三大步,输出了i的值2,j的值12345;
	// 当 i=3时,满足了 i<4的判断条件,执行了第三大步,输出了i的值3,j的值12345;
	// 特点1,外循环执行1次,内循环执行N次
	public static void method(){
		for(int i=1;i<4;i++){  // 外循环执行3次
			System.out.println(i);   // 输出外循环i的值
			for(int j=1;j<6;j++){  // 内循环执行5次
				System.out.println(j);  // 输出内循环j的值
			}
		}
	}
}

(6) 增强 for 循环:foreach语句;
      ① foreach 语句是for语句的特殊简化版本,foreach并不是一个关键字;

      ② foreach格式:

for(元素数据类型 变量名 : 数组或者Collection集合){
	// 在此处使用变量即可,该变量就是元素
}

      ③ foreach范例:

int[] arr ={1,2,3,4,5}
for(int i:arr){
	System.out.println(i);
}

(7) 跳转控制语句 break和continue —— 用来终止循环
      ① break语句

  • break语句用来终止当前循环,简单粗暴(用于循环中,基于条件控制,终止循环体内容的执行,也就是说结束当前的整个循环)
  • 使用break语句的形式:
// for
for(){
	...
	break;
	...
}


// while
while(...){
	...
	break;
	...
}

// do...while
do{
	...
	break;
	...
}while(...);

      ② contonue 语句:跳出本次循环,执行下一轮循环(用在循环中,基于条件控制,跳过本次循环,回到循环的条件判断部分,继续下一次的执行)

      ③ 测试break和continue

package com.java.test;

// 测试break和continue
public class Test5{
	public static void main(String[] args){
		for(int i=1;i<=100;i++){
			if(i%2 == 0){
				// 1.break和contionue都必须出现在循环结构中
				System.out.println(i);
				// break;  // 立刻结束
				continue;  // 结束这次,还能继续
				// 2.break和continue之后不能再出现代码,否则是不可到达的代码
			}
		}
	}
}
3.3.3 while 循环语句(先判断,再执行)

注意:do…while 先执行,再判断

(1) while 条件判断语句,循环方式为利用一个条件来控制是否要继续反复执行这个语句——先判断,再执行;

(2) while 循环语句格式:
while循环语句
(3) while循环执行流程

  • 执行初始化语句;
  • 执行条件判断语句,看其结果是true还是false(如果是true,则继续执行;如果是false,循环结束)
  • 执行循环体语句;
  • 执行条件控制语句;
  • 回到第二步继续;

(4) while 循环 案例

  • 要求:世界最高峰是珠穆朗玛峰(8844.43米 = 8844430毫米),假如有一张足够大的纸,它的厚度是0.1毫米,请问折叠多少次,可以折成珠峰高度?
  • 示例代码:
public class WhileTest{
	public static void main(String[] args){
		// 定义一个计数器,初始值为0
		int count =0;
		// 定义纸张厚度
		double paper = 0.1;
		// 定义珠穆朗玛峰的高度
		int zf = 8844430;
		// 因为是反复折叠,所以要使用循环,但是不知道折叠多少次,这种情况下使用while循环
		// 折叠的过程中当纸张的厚度大于珠峰就停止了,因此继续执行的要求是纸张厚度小于珠峰高度
		while(paper <= zf){
			// 循环执行过程中,每次纸张折叠,纸张的厚度要加倍
			paper *= 2;
			// 在循环过程中执行累加,对应折叠了多少次
			count ++;
		}
		// 打印计数器的值
		System.out.println("需要折叠:" + count + "次");
	}
}
3.3.4 do…while 循环语句(先执行,在判断)

(1) do…while循环和while循环的区别
      ① while 语句为先判断条件是否成立,再执行循环体;
           do…while 循环则先执行一次循环后,再判断条件是否成立;
           也就是说,do…while循环中“{循环体语句}”至少要被执行一次;

      ② do…while 语句在结尾处多了一个分号;

(2) do…while 循环语句格式

do...while循环
(3) do…while 执行流程

  • 执行初始化语句
  • 执行循环体语句;
  • 执行条件控制语句;
  • 执行条件判断语句,看其结果是true还是false(如果是true,继续执行下一步;如果是false,循环结束)
  • 回到第二步继续;

(4) do…while 案例:猜数字,产生一个随机数和用户一直在输入的数字比较;

package com.java.test;
import java.util.Random;
// 测试while循环
// 产生一个随机数,和用户一直在输入的数字相比较
public class Test3{
	public static void main(String[] args){
		// 1.产生随机 整数 -nextInt(N)- 产生N范围内的随机数(默认从0开始)
		int suiji = new Random().nextInt(100) +1;
		System.out.println(suiji);
	
		// 死循环 -- 本质就是因为条件永远成立
		// for(int i=0;i<10;i--){
			// 先判断,再执行,如果没有满足判断条件,一次也不会执行
			// while(suiji > 50){}
			// while(true){}
			do{
				// 2.接收用户输入的数字
				int input = new Scanner(System.in).nextInt();
				// 3.开始比
				if(input > suiji){
					System.out.println("大了");
				} else if(input < suiji){
					System.out.println("小了");
				} else if(input == suiji){
					System.out.println("猜中了!!!");
					break;
				}
			} while (true);
		}
	}
}
3.3.5 for 循环和while循环的区别
  • for 循环是适合有明确循环此时的情况下;
  • while 循环适合循环次数不明确的情况
3.3.6 for循环、while循环、do…while循环的区别

(1) 相同点:都可以解决重复执行问题;

(2) 不同点:

  • for循环要求知道开始位置,要循环多少次,变化的规律;
  • while循环要求知道循环的条件,满足就执行,不满足就不执行;
  • do…while循环要求知道循环的条件,保证循环体最少要执行一次;
  • for知道循环次数;while/do…while用在不确定循环次数;
3.3.7 死循环

(1) 死循环的本质是因为循环条件永远成立 —— 所以必须配合break结束循环;

(2) 死循环格式

// for
for(;;){
	System.out.println("for");
}

// while
while(true){
	System.out.println("1");
}

// do...while
do{
	System.out.println("1");
}while(true);

(3) 测试死循环

package com.java.test;

// 测试 死循环
public class Test4{
	public static void main(String[] args){
		// TODO 死循环的不同写法
		// for(int i=1;i>0;i++){
		// 	for(;;){
		// 		while(true){
		// 			System.out.println(1);
		// 		}
		// 	}

		// TODO while 和 do...while 的区别
		int 1 =10;
		// while(i>10){  // 先判断再执行
		// 	System.out.println(1);
		// }
		}

		do{  // 先执行再判断
			System.out.println(1);  // 保证循环体最少执行1次
		}while(i>10);

		// TODO 假设你有1个亿,一天花一半,能花多少天
		int money = 100000000;  // 定义变量,记录钱
		// 定义变量,记录天数
		int day = 0;
		while(money > 0){
			// 一天花50000000,并修改变量的值
			money = money-50000000;
			day++;  // 统计天数;
		}
		System.out.println("能花:" +day+ "天。");  // 20
	}
}

============================================

4.方法 method

4.1 方法概述:

方法(method)是将具有独立功能的代码块组织成一个整体,使其具有特殊功能的代码集;
注意:

  • 方法(method)必须先创建才可以使用,该过程称为方法定义;
  • 方法(method)创建后并不是直接运行的,需要手动使用后才执行,该过程称为方法调用;

4.2 方法的定义和调用

(1) 无参数方法定义和调用
      ① 无参方法定义格式:

// 无参方法定义格式:
public static void 方法名(){
	// 方法体;
}

// 无参方法定义范例
public static void isEven(){
	// 方法体;
}

      ② 无参方法调用格式:

// 无参方法调用格式:
方法名();

// 无参方法调用范例:
isEven();

      ③ 注意:方法必须先定义后调用,否则程序将报错;方法要在main方法里面调用,因为main是程序的入口方法;

(2) 带参数方法的定义和调用(参数由数据类型和变量名组成: 数据类型 变量名)

      ① 带参数方法定义和调用:

// 带参数方法定义
public static void 方法名(参数){...}

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

      ② 单个参数方法定义和调用

// 单个参数方法定义 格式
public static void 方法名(数据类型 变量名){...}

// 单个参数方法定义 范例
public static void isEven(int num){...}

// 单个参数方法调用 格式
方法名(变量名/常量值);

// 单个参数方法调用 范例
isEven(5);

      ③ 多个参数方法定义和调用:

// 多个参数方法定义 格式
public static void 方法名(数据类型 变量名1,数据类型 变量名2,...){...}

// 多个参数方法定义 范例
public static void isEven(int num1,int num2,...){...}


// 多个参数方法调用 格式
方法名(变量名1/常量值1,变量名2/常量值2,...);

// 多个参数方法调用 范例
getMax(5,6);

      ④ 带参数方法定义注意事项:

  • 方法定义:方法定义时,参数中的数据类型和变量名都不能缺少,缺少任意一个都报错;方法定义时,多个参数使用逗号(,)分隔
  • 方法调用时,参数的数量与类型必须与方法定义中的设置相匹配,否则程序将报错;

4.3 方法的形参和实参

(1) 参数定义:参数是定义方法时规定的该方法运行需要使用的变量;

(2) 形参和实参
      ① 形参:方法定义中的参数;如 int number;
在这里插入图片描述

      ② 实参:方法调用中的参数;如 10 / number;
在这里插入图片描述

4.4 带返回值方法的定义和调用

(1) 带返回值方法定义:

      ① 定义:

// 带返回值方法定义格式:
public static 数据类型 方法名(参数){
	return 数据;
}

// 范例:
public static int getMax(int a,int b){return 100}

      ② 范例:
在这里插入图片描述
      ③ 注意:方法定义时,return 后面的返回值与方法定义上的数据类型要匹配,否则会报错;

(2) 带返回值方法调用:
      ① 带返回值方法调用格式:

// 带返回值方法调用 格式1
// 方法名(参数);
isEven(5);

// 带返回值方法调用 格式2
// 数据类型 变量名 = 方法名 (参数)
boolean flag = isEven(5);

      ② 注意:

  • 方法的返回值通常会使用变量接收,否则该返回值将无意义;
  • 需要再写一个输出(写在调用之后)

4.5 方法的注意事项:

(1) 方法不能嵌套定义;

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

4.6 方法的两个明确

(1) 返回值类型 boolean/int/float…

(2) 参数,如:int[] arr;

4.7 方法的通用格式

(1) 方法的通用格式

public static 返回值数据类型 方法名(参数){
	方法体;
	return 数据;
}
  • public static:修饰符,目前先记住这个格式;
  • 返回值类型:方法操作完毕之后返回的数据类型;如果方法操作完毕,没有数据返回,这里写void,而且方法体中一般不写return;
  • 方法名:调用方法的时候使用的标识;
  • 参数:由数据类型和变量名组成,多个参数之间用逗号“,”隔开;
  • 方法体:完成功能的代码块;
  • return:如果方法操作完毕,有数据返回,用于数据返回调用者;

(2) 定义方法时:

      ① 要明确方法操作完毕之后是否有数据返回,如果没有,在返回值类型处写void,如果有,写对应的数据类型;

      ② 明确参数:主要是明确参数的类型和数量;

(3) 调用方法时:

      ① void 类型的方法,直接调用即可;

      ② 非 void 类型的方法,推荐用变量接收调用;

4.8 方法重载 @Overload

(1) 方法重载 @Overload 概述:方法重载是指同一个类中多个方法,可以有相同的方法名称,但是有不同的参数列表,这就称为方法重载(method overloading)
(重点:看方法名和参数列表,必须是同一个类中)

(2) 构成重载的多个方法需要满足以下条件:

      ① 多个方法在同一个类中;

      ② 多个方法具有相同的方法名;

      ③ 多个方法的参数不相同,类型不同,或者数量不同;

注意:参数列表又叫参数签名,包括参数的类型、参数的个数、参数的顺序,只要有一个不同就叫做参数列表不同;

(3) 方法重载的特点:

      ① 重载对应方法的定义,与方法调用无关,调用方式参照标准格式;

      ② 重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说,不能通过返回值来判定两个方法是否相互构成重载;

(4) 方法重载注意事项:

      ① 与返回值无关;

      ② 在调用的时候,Java虚拟机会通过参数的不同来区分同名方法;

(5) 方法重载案例:

package com.java.test;

// 本类用于测试方法的重载
public class TestMethodOverload{
	public static void main(String[] args){
		// 1.我们根据方法名+参数列表确定具体调用哪个方法
		/**
		* 方法的重载:
		* 在同一个类中,存在方法名相同,但参数列表不同的方法
		* 如果在同类中,同名方法的参数个数不同,一定构成重载
		* 如果在同类中,同名方法的参数个数相同
		* 需要查看对应位置上参数的类型,而不是参数名,与参数名无关
		* (int a,String b) 与 (int b,String a) 不构成重载
		* (int a,String b) 与 (String a,int b) 构成重载
		*/

		// 2.调用 method()
		method();
		// 调用 method(int)
		method(666);
		// 6.调用method(int,String)
		method(888,"泡泡");
	}

	// 1.创建一个无参的 menthod()
	public static void method(){
		System.out.println("我没参数");
	}

	// 3.创建一个 method(int n)
	public static void method(int n){
		System.out.println("我的参数是:" + n);
	}

	// 5.创建一个 method(int n,String s)
	public static void method(int a,String b){
		System.out.println(b + "今晚要干他" +a+ "碗大米饭");
	}
	public static void method(String a,int b){
		System.out.println(b + "今晚要干他" +a+ "碗大米饭");
	}
}

4.9 方法重写 @Override

4.9.1 概述

(1) 方法重写 @Override,发生在父子类里的关系;

(2) 子类继承了父类以后,可以使用父类的所有功能,如果想改 —— 方法重写;

(3) 语法要求:要有足够的权限(子类的权限要 >= 父类原来的权限);子类的方法签名 / 声明必须和父类一样

(4) 访问权限 public > protected > default > private
注意:
      ① 父类中的私有方法不能被重写;

      ② 子类重写父类方法时,修饰符要大于等于父类修饰符的权限;

4.9.2 @Override 注解:用来检测当前的方法,是否是重写的方法,起到[校验]的作用;
4.9.3 方法重写(@Override)和方法重载(@Overload)的区别

(1) 重载(@Overload):是指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,即参数的数量或参数类型不能完全相同;

(2) 重写(@Override):是存在子父类之间的,子类定义的方法与父类中方法具有相同的方法名字,相同的参数列表和相同的返回类型;

(3) 重写是父类与子类之间多态性的一种表现;

(4) 重载是一类中多态性的一种表现;

4.10 方法的参数传递:

(1) 对于基本数据类型的参数,形参的改变,不影响实际参数的值;

(2) 对于引用类型的参数,形参改变,影响实际参数的值;

============================================

4.11 构造方法:

(1) 构造方法概述:
      ① 构造方法是一种特殊方法,它是一个与类同名且返回值类型为同名类类型的方法;对象的创建就是通过构造方法来完成,其功能主要是完成对象的创建或者对象的初始化(java构造方法作用就是对类进行初始化);

  • 当类实例化(new)一个对象时会自动调用构造方法;
  • 构造方法和其他方法一样也可以重载;

      ② 构造方法的语法、用法、作用都和普通方法不一样:
          普通方法语法: 修饰符 返回值 方法名 ([参数列表]) {方法体}
          普通方法作用: 主要用来完成指定的业务;

          构造方法语法:修饰符 类名([参数列表]) {方法体}
          构造方法作用:主要用来完成对象的创建和对象的初始化;

(2) 构造方法的特点

  • 构造方法没有返回值;
  • 构造方法的名称要与本类的名称相同;

(3) 测试构造方法:

package com.java.test;

// 测试 构造方法
/**
 * 总结
 * 1.作用:可以用来new+可以给成员变量赋值
 * 2.语法:修饰符 类名([参数列表]){方法体}
 * 3.构造方法什么时候触发?  new时
 * 4.构造方法会隐藏着一个无参的构造方法,但是当只是提供含参构造方法时,无参
 * 5.为了外界new方便,提供重载的构造方法
 * 6.很少有构造方法私有化private的
 */
public class Tset01{
	public static void main(String[] args) {
		// 1.创建对象时自动触发 构造方法
		// 2。创建对象实例化时 new 时自动触发 构造方法
		new Person();  // 无参数触发的时候直接new就可以(不能只提供含参构造)
		new Person("赵四");  // 自动触发String的构造方法
		new Person("赵四",50);  // 自动触发 String 和 int的构造方法
	}
}

class Person{
	//TODO 构造方法的语法 -- 修饰符 类名([参数列表]){方法体}
	// 1.无参的构造方法,默认就存在,是隐藏的
	public Person() {
		System.out.println("无参数 构造方法");
	}
	
	private String s;
	// 2.构造方法是一个特殊的方法,可以方法重载(重载是指在一个类里面的方法名相同,但参数列表不同的现象)
	public Person(String name) {
		s = name;
		System.out.println(name);
	};
	public Person(int age) {
		System.out.println(age);
	}
	public Person(String name,int age) {
		System.out.println(name + age);
	}
}

5.数组(Array)

5.1 数组概述

  • 数组是具有相同数据类型的一组数据的集合;
  • 数组(Array)的标志是 [];
  • 数组的每个元素都有下标/索引(index),默认从0开始;

(1) 创建数组格式:

数组格式

(2) 数组的初始化:也可以理解为给数组赋值;

      ① 所谓初始化:就是为数组中数组元素分配内存空间,并为每个数组元素赋值;

      ② Java 中的数组必须先初始化,然后才使用;

      ③ 数组的初始化方式:动态初始化和静态初始化;

(3) 数组的动态初始化

      ① 概述:动态初始化指的是初始化时只指定数组的长度,由系统为数组分配初始值;

      ② 数组的动态初始化格式:

动态数组
(4) 数组的静态初始化:

      ① 静态初始化是指初始化时指定每个数组元素的初始值,由系统决定数组长度(即在创建数组时,直接将元素确定);

      ② 静态初始化格式:

数组静态初始化格式

(5) 数组元素访问

      ① 访问方式:

  • 数组变量访问方式 格式: 数组名;
  • 数组内部保存的数据的访问方式 格式: 数组名[索引]

      ② 索引(index)是数组中数据的编号方式

  • 索引的作用:用于访问数组中的数据使用,数组名[索引]等同于变量名,是一种特殊的变量名;
  • 索引的特征:从0开始,连续,逐一增加,每次加1;

(6) 数组内存分配

      ① 内存概述:内存是计算机中的重要原件,临时存储区域,作用是运行程序;

      ② Java中的内存分配:

  • 栈内存:存储局部变量(定义在方法中的变量,例如:arr),使用完毕后立即消失;
  • 堆内存:存储对象或者数组,new来创建的,都存储在堆内存,即存储new出来的内容(实体、对象);每一个new出来的东西都有一个地址值,使用完毕后,会在垃圾回收器空闲时期被回收;
  • 数组在初始化时,会为存储空间添加默认值: 整数 0 ;浮点数 0.0; 布尔 false; 字符:空字符; 引用数据类型:null

(7) 数组的长度:length 属性获取数组长度,数组一旦创建,长度不可变,允许0长度的数组;

5.2 数组操作的两个常见问题;

(1) 索引越界:访问了数组中不存在的索引对应的元素,造成索引越界问题 ArrayIndexOutOfBoundsException

(2) 空指针异常:访问的数组已经不再指向堆内存的数据,造成空指针异常 NullPointerException

(3) null:空值,引用数据类型的默认值,表示不指向任何有效对象

5.3 数组练习1:数组中存入 hello

package com.java.tt

// 测试 数组
public class Test1{
	public static void main(String[] args){
		// 1.创建数组,存入hello
		// 静态初始化
		char[] a = new char[] {'h','e','l','l','o'};
		char[] b = {'h','e','l','l','o'};
		System.out.println(a);
		System.out.println(b.length);

		// 动态初始化  获取了数组的长度
		char[] c = new char[5];
		c[0] = 'h';  // 修改
		System.out.println(c[0]);  // 查看
		// TODO 修改其他位置的默认值 \u0000
		c[1] = 'e';  // 修改
		c[2] = 'l';  // 修改
		c[3] = 'l';  // 修改
		c[4] = 'o';  // 修改

		// TODO 数组下标越界异常,因为访问了不存在的下标
		// java.lang.ArrayIndexOutOfBoundsException;
		// c[5] = 'x';  // 不存在的下标5
		System.out.println(c.length);
	}
}

5.4 数组常见操作:

(1) 数组遍历

      ① 数组遍历概述:就是将数组中的每个元素分别获取出来,就是遍历;遍历也是数组操作中的基石;

      ② 遍历数组通用格式:

int[] arr = {...};
for(int x=0;x<arr.length;x++){
	arr[x];  // 对arr[x]进行操作
}


// 获取数组元素数量 格式
数组名.length;

arr.length;

      ③ 数组遍历的基本用法:

public class ArrayTest01{
	public static void main(String[] args){
		// 定义数组
		int[] arr = {11,22,33,44,55}

		// 使用通用的遍历格式
		for(int x=0;x<arr.length;x++){
			System.out.println(arr[x])
		}
	}
}

      ④ 遍历数组练习:

package com.java.basic;

import java.util.Random;

// 测试 遍历数组
public class Test2{
	public static void main(String[] args){
		// method();  // 遍历数组入门
		// method2();  // 输出每个月的天数
		// method3();  // 存入1到10
		// method4();  // 存入10个随机数
		method5();  // 统计数组里 偶数的和
	}

	// 统计数组里 偶数的和
	public static void method5(){
		// 1.创建数组
		int[] a = {37,65,28,22,57,70,40,96,57,50}
		
		// 2.遍历数组
		int sum = 0;  // 定义变量,记录和
		for(int i=0;i<a.length;i++){
			// 过滤出来偶数
			if(a[i] % 2 == 0){
				// 修改和=原来的值+新偶数
				sum = sum + a[i];
			}
		}
		System.out.println(sum);  // 打印和
	}

	// 存入10个随机数
	public static void method4(){
		// 1.创建数组
		int a[] = new int[10];

		// 2.遍历数组
		for(int i=0;i<a.length;i++){
			// 把每个位置的元素,从默认值修改成 随机数
			a[i] = new Random().nextInt(100);
		}
		
		// 3.打印数组里的数据
		System.out.println(a);  // [I@6d06d69c 地址值
		for(int i=0;i<a.length;i++){
			System.out.println(a[i] + ","); 
		}
	}

	// 存入1到10
	public static void method3(){
		// 1.创建数组
		int a[] = new int[10];

		// 2.遍历数组
		for(int i=0;i<a.length-1;i++){
			a[i] = i+1;  // 改
			System.out.println(a[i]);   // 查看
		}
	}

	// 输入每个月的天数
	public static void method2(){
		// 1.创建数组
		int[] a = {31,29,31,30,31,30,31,30,30,30,30,31};
		// 2.根据下标遍历数组
		for(int i=0;i<a.length;i++){
			// i+1 是为了取到 1~12月,i是0~11,加1就是1~12
			// a[i]是根据下标获取a数组里的数据
			System.out.println(i+1+"月有"+a[i]+"天"); 
		}
	}

	// 遍历数组的入门
	public static void method(){
		// 1.创建数组
		// a是引用类型的变量,存的是地址值
		int[] a = new int[5];  // a 数组现在存的是默认值0
		System.out.println(a);   // [@15db9742,地址值
		for(int i=0;i<length-1;i++){
			a[i] = 1; // 修改
			System.out.println(a[i]);   // 根据下标,输出a数组里的数据
		}
	}
}

(2) 数组最值

      ① 需求:最大值获取——从数组的所有元素中找出最大值;

      ② 实现思路:

  • 定义变量,保存数组0索引上的元素;
  • 遍历数组,获取触数组中的每个元素;
  • 将遍历到的元素和保存数组0索引上值的变量进行比较;
  • 如果数组元素的值大于了变量的值,变量记录新的值;
  • 数组循环遍历结束,变量保存的就是数组中的最大值;

      ③ 代码实现:

public class ArrayTest02{
	public static void main(String[] args){
		// 定义数组
		int[] arr = {12,45,98,73,60}

		// 定义一个变量,用于保存最大值
		// 取数组中第一个数据作为变量的初始值
		int max = arr[0];
		// 与数组中剩余的数据逐个对比,每次比对将最大值保存到变量中
		for(int x=1;x<arr.length;x++){
			if(arr[x] > max){
				max = arr[x];
			}
		}
		// 循环结束后打印变量的值
		System.out.println("max:" + max);
	}
}

5.5 数组工具类 Arrays

(1) 概述:专门为数组提供了很多方法;

(2) 常用方法:

      ① Arrays.toString(数组) —— 把数组里的数据,用逗号连接成一个字符串,如:[10,14,20,46,51]

      ② Arrays.sort(数组) —— 把数组里的数据进行排序;

      ③ Arrays.copyOf(数组,新的长度) —— 解析:

  • 把数组复制成一个指定长度的新数组;
  • 新数组长度大于原数组,相当于复制,并增加位置 —— 数组的扩容;
  • 新数组长度小于原数组,相当于截取前一部分数据 —— 数组的缩容;

(3) 测试数组的工具类

package com.itheima.reggie;

import java.util.Arrays;

// 测试 数组的工具类
public class Test {
	public static void main(String[] args) {
		// method();  // toString()
		// method2();  // sort()
		method3();  // copyOf()
	}
	
	// copyOf()
	public static void method3() {
		// 1.创建数组
		int[] a = {5,3,1,2,8,6};
		
		// 复制 -copyOf(1,2)-1 是原数组名-2是新长度
		int[] b = Arrays.copyOf(a, 10);
		
		// 展示b数组里的数据 [5,3,1,2,8,6,0,0,0,0]  扩容(新长度>旧的)
		System.out.println(Arrays.toString(b));
		
		int[] c = Arrays.copyOf(a, 3);
		
		// 展示吃数组里的数据 [5,3,1] 缩容(新长度<旧的)
		System.out.println(Arrays.toString(c));
	}
	
	// sort()
	public static void method2() {
		// 1.创建数组
		int[] a = {5,3,1,2,8,6};
		
		// 排序 —— 默认升序,从小到大
		Arrays.sort(a);
		
		// 打印 [1,2,3,4,5,6,8]
		System.out.println(Arrays.toString(a));
		System.out.println(a[0]);  // 获取数组里的最小值
		System.out.println(a[a.length-1]);  // 获取数组里的最大值
	}
	
	// toString()
	public static void method() {
		// 1.创建数组
		String[] a = {"地理","文学","自然"};
		
		// 2.查看数组里的数据
		System.out.println(a);  // [Ljava.lang.String;@15db9742
		
//		for(int i=0;i<a.length;i++) {
//			System.out.println(a[i]);
//		}
		
		//TODO 用工具类优化 toString(a) —— 展示a数组中的数据
		String res = Arrays.toString(a);
		System.out.println(res);  // [地理,文学,自然]
		
		//TODO 继续优化,省一个变量
		System.out.println(Arrays.toString(a));
	}
}

6.异常

6.1 异常概述:

(1) 异常就是程序出现了不正常的情况,用来封装错误信息的对象;
(2) 组成结构:类型、提示、行号;

6.2 异常的继承结构:

(1) 异常的继承结构示意图:

异常的继承结构示意图

(2) Throwable:顶级父类;

(3) Error:是不能靠程序处理的,系统错误,无法修复,比如内存溢出;

(4) Exception:可修复的错误,称为异常类;

      ① RuntimeException:运行时异常(非检查异常)—— 在编译期是不检查的,出现问题后,需要我们回来修改代码;

         常用的运行时异常:
           a. NullPointerException(空指针异常)当操作一个空引用抛出的异常;

           b. NumberFormatException —— 数据格式化异常,试图将字符串转换为一种数值类型时,但字符串转换不适当出现的异常;

           c. Class CastException —— 类型转换异常,强制类型转换不匹配时出现的异常;

           d. ArrayIndexOutOfBoundsException —— 数组下标越界异常,当使用一个不存在的下标时出现的异常;

           e. ArithmeticException —— 数字异常,异常运算条件时出现的;

      ② 非 RuntimeException:非运行时异常(检查异常)—— 在编译期必须处理的,否则程序不能通过编译;
         常用非运行时异常:
           a. SQLException:访问数据库时出现的;
           b. IOException:当发生某种I /O 异常时抛出的;
           c. ClassNotFoundException:当应用程序使用Class类中的forName方法,loadClass方法时,抛出异常;

6.3 异常处理:

(1) 如果程序遇到了异常,有两种处理方式:

捕获: try...catch
向上抛出:throws
  • 当调用一个含有 throws 声明异常抛出的方法时,编译器要求必须处理这个异常,而处理方式有两种:
      ① 使用 try…catch 处理该异常;
      ② 在当前方法上继续声明throw将该异常抛出;

(2) 捕获方式:

        ① 格式:

try{
	可能出现异常的代码;
} catch(异常类型名 异常名){
	处理方案;
}

/**
 * 释义:
 * try:用来指定一块预防所有异常的程序;
 * catch:用来指定想要捕获的异常
*/

        ② 执行流程:
            a. 程序从try里面的代码开始执行;
            b. 出现异常,会自动生成一个异常类对象,该异常类对象将被提交给Java运行时系统;
            c. 当Java运行时,系统接收到异常对象时,会到catch中去找匹配的异常类,找到后进行异常的处理;
            d. 执行完毕后,程序还可以继续往下执行;

(3) 抛出方式 —— 在会发生异常的方法上添加代码 throws 异常类型;

  • 例如:public static void main(String[] args) throws Exception{}
  • Throwable 的成员方法:
方法名说明
public String getMessage()返回此throwable的详细消息字符串
public String roString()返回此可抛出的简短描述
public void print StackTrace()把异常的错误信息,输出在控制台

(4) Throw 语句用来明确抛出一个异常

  • Throw 用了标明这个方法可能会抛出的各种异常;

(5) try {} catch {} finally {}
      ① finally 块是捕获机制中的最后一块;
      ② finally 可以直接跟在 try 后面或者最后一个 catch之后;
      ③ finally 可以保证只要程序执行到try语句块中,无论try语句块中的代码是否抛出异常,finally块中的代码都必须执行;

★ 注意:

  • 通常会将无论是否出现异常都要运行的代码放在finally中确保运行,比如IO操作中的关闭流;
  • Final 是一个修饰符;
  • Finalize 是方法名,此方法是在垃圾回收器将对象从内存中清除之前做必要的清理工作;

(6) 派生类在继承时会重写其方法,那么在重写超类中含有 throws声明异常抛出的方法时,对throws的重写规则:

  • 可以不再抛出任何异常;
  • 可以仅抛出父类方法抛出的部分异常;
  • 可以抛出父类方法抛出异常的子类型异常;
  • 不允许抛出额外异常;
  • 不允许抛出父类方法抛出异常的父类型异常;

(7) 自定义异常:

      ① 自定义异常 格式:

public class 异常类名 extends Exception{
	无参构造;
	代参构造;
}

      ② 自定义异常 范例:

public class ScoreException extends Exception{
	public ScoreException(){}
	public SoreException(String Message){
		super(message);
	}
}

(8) throws 和 throw 的区别:

throwsthrow
用在方法声明后面,跟的是异常类名用在方法体内,跟的是异常对象名
表示抛出异常,由该方法的调用者来处理表示抛出异常,由方法体内语句处理
表示出现异常的一种可能性,并不一定会发生这些异常执行throw一定抛出了某种异常

6.4 测试 异常 (接收键盘输入两个数字并做除法运算异常)

(1) 接收键盘输入两个数字并做除法运算 – 暴露异常 exception

package com.java.test;

// 测试 -- 暴露异常 exception
import java.util.Scanner; // 导包

public class Test{
	public static void main(String[] args) {
		method();  // 暴露异常;
	}
	
	// 暴露异常
	public static void method() {
		// 1.接受用户输入的两个整数
		System.out.println("请输入两个整数");
		int a = new Scanner(System.in).nextInt();
		int b = new Scanner(System.in).nextInt();
		
		// 2.做除法运算
		System.out.println(a/b);
	}
}

// 输出结果:当输入小数(如 1.5)或字符串(如ab),会报错

(2) 捕获异常

package com.java.test;

// 测试 -- 捕获异常
import java.util.InputMismatchException;
import java.util.Scanner; // 导包

public class Test{
	public static void main(String[] args) {
		method2();  // 捕获异常;
	}
	
	// 捕获异常:自己的问题自己处理,调用者很安全
	/**
	 * try{
	 * 	有问题的代码;
	 * } catch (异常类型 异常名){
	 * 	 给出解决方案;
	 * }
	 */
	public static void method2() {
		try {
			System.out.println("请输入两个数");
			int a = new Scanner(System.in).nextInt();
			int b = new Scanner(System.in).nextInt();
			System.out.println(a/b);
		} catch(ArithmeticException a) {
			System.out.println("第二次输入不能为0");
		} catch(InputMismatchException d) {
			System.out.println("请输入两次整数!");
		} catch(Exception a) {  // 多态
			System.out.println("请输入正确数据!");
		}
	}
}

// 输出结果1:请输入两个数  6/0 → 第二次输入不能为0
// 请输入两个数  1.5 → 请输入两次整数

/**
 * 注意:
 * 不知道有多少个错误时,便不知道catch 几次,这样变解决不了所有的异常,这里可以使用通用的解决方案 —— 多态 Exception
 * 不关心具体的子类类型,把子类当做父类看;
 */

(3) 抛出异常

package com.java.test;

// 测试 -- 抛出异常
import java.util.Scanner; // 导包

public class Test{
	public static void main(String[] args) {
		// method3();  // 抛出异常
		try {
			method3();
		} catch(Exception a) {
			System.out.println("执行错误");
		}
	}
	
	// 抛出异常:交给调用者处理
	// 抛出异常写法是直接在方法声明后添加:throws 异常类型
	public static void method3() throws Exception{
		System.out.println("请输入两个整数");
		int a = new Scanner(System.in).nextInt();
		int b = new Scanner(System.in).nextInt();
		System.out.println(a/b);
	}
}

// 输出结果: 当输入1.5 / abc 时,会输出“执行错误”

6.5 自定义异常实例

(1) 实体类 People

package com.java.test;

// 实体类 People
public class People{
	String name ="";
	int age = 0;
	String sex;
	public String getSex() {
		return sex;
	}
	
	public void setSex(String sex) throws Exception{
		if("男".equals(sex) || "女".equals(sex)) {
			this.sex = sex;
		} else {
			throw new GendorException("性别必须是男或女");
		}
	}
}

(2) 自定义异常类

package com.java.test;

// 自定义异常类
public class GendorException extends Exception{
	public GendorException(String mag) {
		super(mag);
	}
}

(3) 测试类

package com.java.test;

// 测试类
public class Test{
	public static void main(String[] args) {
		// Auto-generated mehtod stub
		People p = new People;
		try {
			p.setSex("Male");
		} catch(Exception e) {
			System.out.println("设置性别出错了");
			e.printStackTrace();  // 输出异常信息
		}
	}
}

五、面向对象

1.面向对象概念

(1) 概念:面向对象编程就是面向一个具体的对象来进行操作; 面向对象是基于面向过程而言的;

(2) 面向对象和面向过程

      ① 面向对象强调结果:
          例如:饿了,去平台点餐,这个动作就是面向对象,但你没有去市场买菜、洗菜、做饭…,只要有app就可以了;

      ② 面向过程强调的是过程;
          例如: 1.打开冰箱 2.把大象放进去 3.关上冰箱

(3) 面向对象三大特征

  • 封装性:把相关的数据封装成一个“类”组件;
  • 继承性:是子类自动共享父类属性和方法,是类之间的一种关系;
  • 多态,增强软件的灵活性和重用性;

(4) 面向对象编程 OOP (Object Oriented Programming)

2.类和对象

  • 类是抽象的,对象是具体的;

2.1 类

(1) 类定义:

  • 类是一类事物的抽象,通过 class 类关键字定义,在客观世界中是不存在的,只是用来描述对象的信息的;
  • Java 语言最基本单位就是类,类似于类型;
  • 类可以理解为模版和设计图纸;

(2) 类的特点:类是对象的数据类型;类是具有相同属性和行为的一组对象的集合;

(3) 类的组成是由属性和行为两部分组成;

      ① 属性:指事物的特征,在类中通过成员变量来实现(类中方法外的变量);例如:手机事物(品牌,价格,尺寸)

      ② 行为:指事物能执行的操作,在类中通过成员方法来实现(和前面的方法相比去掉 static 关键字即可); 例如:手机事物(打电话,发短信)

(4) 类的定义步骤(属性和行为)
      ① 类的定义步骤:

  • 定义类;
  • 编写类的成员变量;
  • 编写类的成员方法;

      ② 类的定义代码格式:

public class 类名{  // 1.定义类;
	// 2.编写类的成员变量;
	变量1的数据类型 变量1;  // 要有数据类型和变量名;
	变量2的数据类型 变量2; 
	...

	// 3.编写类的成员方法;
	方法1;  // 没有static
	方法2;
	...
}

      ③ 类的定义示例代码:

package com.itheima.test;

/** 手机类:
 * 类名:手机(phone)
 * 成员变量:
 * 品牌(brand)
 * 价格(price)
 *  
 *  成员方法:
 *  打电话(call)
 *  发短信(sendMessage)
 */
public class phone {
	// 成员变量
	String brand;
	int price;
	
	// 成员方法
	public void call() {
		System.out.println("打电话");
	}
	
	public void sendMessage() {
		System.out.println("发短信");
	}
}

2.2 对象

(1) 概述:对象是能够看得到摸得着的真实存在的实体,通过new关键字定义;

(2) 对象的特点:对象的状态、对象的行为和对象的标识;

      ① 对象的状态:用来描述对象的基本特征;

      ② 对象的行为:用来描述对象的功能(对象能够执行的操作);

      ③ 对象的标识:是指对象的内存中都有一个唯一的地址用来和其他对象区分开来;

      ④ 类是同一类事物的抽象,对象是具体的实现;

(3) 对象的属性:对象具有的各种特征,每个对象的每个属性,都拥有特定的值;

(4) 对象的使用:
      ① 步骤:新建模块 Modules → 再在模块的.src 文件夹下建立一个包 → 再在这个包下新建一个类 class

      ② 创建对象:

  • 格式: 类名 对象名 = new 类名();
  • 范例: Phone P = new Phone();

      ③ 使用对象:

  • 使用成员变量:

      格式: 对象名.变量名;
      范例: P.brand;

  • 使用成员方法:

      格式: 对象名.方法名();
      范例: P.call();

(4) 创建对象,就是将 同一个包 下的另一个类文件当成对象,并给这个类文件起一个对象名,在另一个类文件下调用、使用;

(5) 对象在内存中的存储

  • Java把内存分成5大区域,我们重点关注栈和堆;

      ① 一般来讲局部变量存在栈中,方法执行完毕内存就被释放;

      ② 对象(new 出来的东西)存在堆中,对象不再被使用时,内存才会被释放;

      ③ 每个堆内存的元素都有地址值;

      ④ 对象中的属性都是有默认值的;

(6) 单一对象内存图:

在这里插入图片描述

      ① 在栈内存中,创建一个引用变量 p,持有对象的地址值;

      ② 在堆内存中,创建Person对象,并且开辟变量的空间,完成初始化;

      ③ 给堆内存中的元素,分配一个唯一标志、地址值,交给 p 去保存;

      ④ p.name=“lisi”; p.age=20; 就去堆内存中找唯一的地址值找到Person对象,并对其属性进行修改、赋值;

      ⑤ p.eat(); 就去堆内存中找唯一的地址值,找到Person对象,执行Person对象的方法;

(7) 创建对象的流程 Person p = new Person();

      ① 把 Person.class文件加载进内存;

      ② 在栈内存中,开辟空间,存放变量P
      ③ 在堆内存中,开辟空间,存放Person对象
      ④ 对成员变量进行默认的初始化;
      ⑤ 对成员变量进行显示初始化;
      ⑥ 执行构造方法(如果有构造代码块,就先执行构造代码块再执行构造方法)
      ⑦ 堆内存完成
      ⑧ 把堆内存的地址值赋值给变量P,P就是一个引用变量,引用了Person对象的地址值;

(8) 匿名对象:
      ① 匿名对象:即没有名字的对象,是对象的简化表示形式;

      ② 使用场景:当被调用的对象只调用一次时(多次会创建多个对象浪费内存)

Demo d = new Demo();
d.sleep();
d.game();

// 这个d就是对象的名字
// 也可以写成
new Demo().show();  // 创建了一个对象调用方法
new Demo().game();  // 又创建了一个对象调用方法

2.3 类的定义和对象的使用

(1) 在一个包内,新建两个类,一个类用来定义类,另一个用来使用类;

(2) 定义类:

定义类

(3) 使用对象

使用对象

(4) 练习:类的创建使用

package com.java.test;

// 测试 OOP
// 一个 .java 文件中,可以存在多个 class
// 要求:只能有一个被public修饰,.java的文件名 =public 的类名
public class Test01{
	public static void main(String[] args) {
		// 2.通过new创建对象
		new Phone().call();  // 匿名对象 + 一次只执行一个任务
		
		// 3. p是引用类型,存地址值
		Phone p = new  Phone();  // 有名字的对象
		System.out.println(p);  // com.java.test.Phone@15db9742
		
		Phone p2 = new Phone(); // 每次new都是产生新的对象
		System.out.println(p2);  // com.java.test.Phone@6d06d69c
		
		// 4.调用模版里的方法
		p.game();
		p.call();
		p.message();
		
		// 5. 调用模版里的属性
		System.out.println(p.size);  // 0.0
		System.out.println(p.pinpai);  // null
		System.out.println(p.color);  // null
		
		// 设置属性的值
		p.size = 5.7;
		p.pinpai = "VIVO";
		p.color = "blue";
		
		// 获取属性的值
		System.out.println(p.size);  // 5.7
		System.out.println(p.pinpai);  // VIVO
		System.out.println(p.color);  // blue
		
		//TODO 练习:给p2对象设置值/获取值
		p2.game();
		p2.call();
		p2.message();
		
		p2.size = 7.8;
		p2.pinpai = "HUAWEI";
		p2.color = "green";
		System.out.println( p2.size );
		System.out.println( p2.pinpai );
		System.out.println( p2.color );
	}
}

// 1.创建手机类 -- 用来描述手机事物
class Phone{
	// 特征 -- 属性/成员变量(类里方法外)
	double size;  // 大小
	String pinpai;  // 品牌
	String color;  // 颜色
	
	// 功能:方法/成员方法(类里方法外)
	// 方法的修饰符 方法的返回值 方法名([参数列表]){方法体}
	public void game() {
		System.out.println("王者...");
	}
	public void call() {
		System.out.println("打电话...");
	}
	public void message() {
		System.out.println("发短信...");
	}
}

2.3 类和对象的关系

(1) 类:类是对现实生活中一类具有共同属性和行为的事物的抽象;

(2) 对象:对象是能够看得到摸得着的真实存在的实体;

(3) 对象是计算机中具体的数据信息,而类就是这个信息的数据类型;

(4) 类是对象的抽象,对象是类的实体;

(5) 类和对象关系示意图:

类和对象关系示意图

3.封装 private

3.1 定义:

(1) 封装是指隐藏对象的属性和实现细节,仅仅对外提供公共的访问方式;

(2) 封装的好处是提高安全性,提高重用性;

3.2 private 关键字

(1) private 关键字是一个权限修饰符,用于修饰成员变量和成员方法(函数),被私有化的成员只能在本类中访问,不能被别的类使用;

(2) 想要修改只能对外提供公共的 get 和 set 方法;

(3) 针对 private 修饰的成员变量,如果需要被其他类使用,提供相应的操作:

      ① 提供 “get 变量名()” 方法,用于获取成员变量的值,方法用public修饰;

      ② 提供 “set 变量名()” 方法,用于设置成员变量的值,方法用public来修饰;

      ③ 先设置 set,后获取 get

      ④ 注意:“get 变量名()” 和 “set 变量名()” 变量名的首字母要大写;

      ⑤ set / get 快捷键生成

  • Eclipse中:右键 → source → generate getters ands setters → select all → OK;
  • IDEA中: 右键 → Generate → Getter and Setter;

3.3 测试封装 private

(1) 创建 student 类

package com.java.test;

// 测试封装 private
/**
 * 总结:
 * 1.通过private 关键字,实现封装,提高资源的安全性(只能本类里访问) 
 * 2.当属性被private封装后,需要提供public 的 getXxx()获取值 / setXxx
 */
public class Student{
	//TODO Fields -- 成员变量,也叫实例变量
	private String name;  // 使用private封装后,在其他类中不可见,不能使用
	int no;
	private char sex;
	
	// 4.给外界提供设置方式 set() 方法
	public void set(String s) {
		name = s;  // 给name属性赋值
	}
	
	// setXxx() -- 就是为外界提供设置属性的方式
	public void setNo(int a) {
		no = a;  // 给no属性赋值
	}
	
	// setXxx() -- 就是为外界提供设置
	public void setSex(char b) {
		sex = b;  // 给sex属性赋值
	}
	
	// 3.给外界提供一个 获取方式 get 方法
	public String get() {
		return name;  // 给外界返回name属性;
	}
	
	// getXxx() -- 就是为外界提供获取属性的方式
	public int getNo() {
		return no;
	}
	
	// getXxx() -- 就是为外界提供获取
	public char getSex() {
		return sex;
	}
	
	//TODO Methods -- 方法 / 函数
	private void coding() {  // 使用private封装方法时,不能和public同时出现
		System.out.println("我爱java");
	}
	public void game() {
		// 因为coding()被封装了,只能在本类中访问,相当于给外界提供间接的访问方式
		coding();
		System.out.println("王者");
	}
}

(2) 创建封装测试类:

package com.java.test;

// 测试封装 private
public class Tset01{
	public static void main(String[] args) {
		//TODO 创建 Student 对象
		Student s = new Student();
		
		// 调用方法
		// s.coding();  // 因为 coding() 被封装了,无法使用
		s.game();
		
		// 设置属性
		// s.name="王二狗";  // 因为name被封装了,无法使用
		// s.no=100;
		// s.sex='男';
		
		s.set("张大拿");  // 设置值
		s.setNo(1);
		s.setSex('男');
		// String name = s.get();
		
		// 获取属性 -- 赋值/获取
		// System.out.println(s.name);  // 因为name被封装了,无法使用
		System.out.println(s.get());  // 获取值
		
		// System.out.println(s.no);
		System.out.println(s.getNo()); // 获取值
		
		// System.out.println(s.sex);
		System.out.println(s.getSex);  // 获取值
	}
}

4.构造代码块和局部代码块

(1) 代码块概述:

  • 代码块是一段代码被花括号“{}”包起来;
  • 代码块根据出现的位置不同,语法用法作用都不同;
  • 出现在成员位置(类里方法外)的代码块 —— 构造代码块;
  • 出现在局部位置(方法里)的代码块 —— 局部代码块;

(2) 构造代码块

  • 在类的内部、方法外部的代码块;
  • 通常用于抽取构造方法中的共性代码;
  • 每次调用构造方法前都会调用构造代码块;
  • 优先于构造方法加载;

      ① 构造代码块 示例

class C{
	// 构造代码块
	String country;
	{
		country = "中国";
	}

	public c(){
		System.out.println("1号选手,来自" + country);
	}
}

(3) 局部代码块:

  • 在方法里面的代码块;
  • 通常用于控制变量的作用范围,出了括号就失效;
  • 变量的范围越小越好,成员变量会有线程安全问题;
  • 执行顺序:构造代码块是最优先的,局部代码块顺序执行;

      ① 局部代码块 代码示例:

class Student{
	{
		System.out.println("构造代码块");
	}

	public void init(){
		// 局部代码块
		{
			System.out.println("局部代码块");
		}
	}
}

(4) 测试构造代码块

package com.java.test;

// 测试 构造代码块
/**
 * 总结
 * 1.构造代码块,作用是提取构造方法的共性代码+位置是在类里方法外
 * 2.构造方法,作用是new/赋值+位置是在类里方法外
 * 3.局部代码块:作用是控制变量的作用范围+位置是在方法里
 * 4.执行顺序:
 *         当new时,先执行构造代码块再执行构造方法
 *         当方法被调用时,才执行局部代码块
 */
public class Tset01{
	public static void main(String[] args) {
		//TODO
		new Teacher();
		new Teacher(10);
		new Teacher("Jack");
		new Teacher("男");
		new Teacher("Jack",20);
		
		new Teacher().show();
	}
}

class Teacher{
	//TODO 2.构造代码块,位置是在
	{
		// 提取了所有构造方法里的重复代码 -- 提高了代码的复用性
		System.out.println("构造代码块");
	}
	
	//TODO 1.构造方法/Construtors...
	public Teacher() {}
	public Teacher(int a) {}
	public Teacher(String b) {}
	public Teacher(char c) {}
	public Teacher(String b,int a) {}
	
	public void show() {
		int a = 0;  // 局部变量(在方法里面的),局部变量就近原则,优先使用局部变量
		System.out.println(a);
		// 3.局部代码块 -- 位置是在方法里,用来控制变量的作用范围
		// 当方法被调用时,局部代码块才会被触发
		{
			int b = 10;
			System.out.println("局部代码块");
		}
	}
}

(5) 访问控制符 – 用来控制一个类,或者类中的成员的访问范围

子类任意
public
protected
default
private

5.继承 extends

5.1 继承概述:

(1) 继承 extends 是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法;

(2) 实现继承的格式 – 继承通过extends实现;

  • 格式: public class 子类名 extends 父类名{};
  • 范例: public class Zi extends Fu{};

释义:Fu:是父类,也被称为基类、超类;
            Zi:是子类,也被称为派生类;

(3) 继承特点:

  • 使用 extends 关键字;
  • 相当于子类把父类的功能复制了一份;
  • Java只支持单继承;
  • 继承可以传递;
  • 不能继承父类的私有成员;
  • 继承多用于功能的修改,子类可以拥有父类的功能的同时,进行功能扩展;
  • 像是 is a 的关系;

      ① 继承中子类的特点:

  • 子类可以有父类的内容;
  • 子类还可以有自己特有的内容;

(4) 继承的好处和弊端:

      ① 继承的好处:

  • 继承可以让类与类之间产生关系,子父类关系,产生子父类关系后,子类则可以使用父类中非私有成员;
  • 提高了代码的复用性(多个类相同的成员可以放到同一个类中)
  • 提高了代码的维护性(如果方法的代码需要修改,修改一处即可)

      ② 继承的弊端 —— 继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时,子类实现也不得跟着变化,削弱了子类的独立性;

(5) 测试继承

package com.java.test;

// 测试 继承
// extends 这种继承关系耦合性太强,依赖关系太强,只能单继承,所以不太提倡
public class Tset01{
	public static void main(String[] args) {
		// 创建子类对象测试
		Dog d = new Dog();
		d.eat();  // 用了父类;
		d.sleep();  // 用了父类的
		System.out.println(d.fangqian);
		
		// 继承的传递性
		dahuang dh = new dahuang();
		dh.eat();
		dh.sleep();
		dh.kanjia();
	}
}

// 1.创建父类 -- 提取子类所有共性的代码/提高了父类代码的复用性
class Animal{
	// 2.3 子类不能继承父类的私有资源
	double sifangqian = 5;
	public void eat() {
		System.out.println("啥都行");
	}
	public void sleep() {
		System.out.println("在睡觉");
	}
}

// 2.创建子类 -- 使用extends 关键字,继承父类后,减少了代码的编写
class Dog extends Animal{
	// 2.1 java只支持单根继承,一个子类只能继承一个父类,也不能继承父类的私有成员 private
	// 2.2 相当于子类把父类的功能复制了一份
	public void kanjia() {
		System.out.println("看家");
	}
}

class dahuang extends Dog{}

(7) 什么时候使用继承?

  • 使用继承需要考虑类与类之间是否存在 is…a 的关系,不能盲目使用继承;
  • is…a 的关系:谁是谁的一种;例如:猫和动物;

5.2 继承中的用法

(1) 继承里的成员变量

package com.java.test;

// 测试 继承里的成员变量
public class Tset01{
	public static void main(String[] args) {
		//TODO 创建对象测试
		new Zi().show();
		
		// 对属性的操作:要么打印要么赋值
	}
}

class Fu{
	String name = "Jack";
}

class Zi extends Fu{
	String name = "rose";
	int age = 20;  // 成员变量
	
	public void show() {
		int age = 10;  // 局部变量
		System.out.println(age);  // 10.就近原则,优先使用局部变量
		System.out.println(this.age);  // 20.this调用了本类的成员变量
		System.out.println(name);  // 使用了子类的资源 rose
		// 1.super代表父类对象的引用。  Fu super = new Fu();
		// 2.super用在子类中,调用父类的功能
		System.out.println(super.name);  // 使用了父类的资源 jack
	}
}

(2) 继承里的方法

package com.java.test;

// 测试 继承里的方法
// 总结:
// 1.子类,可以使用继承自父类的所有方法(除了private的)
// 还可以 扩展自己的特有的方法
// 还可以 修改继承来的方法 -- 方法的重写
// 语法要求:有足够的权限 (>=) + 子类的方法声明/签名 必须和父类一样
// 2.方法重写:影响了子类的方法体。但是对父类不能产生影响
// 3.开发时的原则,ocp开闭原则 -- 关闭源码修改 -- 开发功能扩展
public class Tset01{
	public static void main(String[] args) {
		Zi z = new Zi();
		z.eat();  // 重写前,使用了父类的;重写后,使用了子类的;
		// z.play();  // 是父类的私有资源,只能在父类中使用
		// z.coding();  // 使用了子类扩展的
	}
}

class Fu{
	public void eat() {
		System.out.println("啥都吃");
	}
	
	private void play() {
		System.out.println("啥都玩");
	}
}

// 1.子类继承父类后,可以使用父类的所有方法(除了private的)
class Zi extends Fu{
	// 3.子类除了能用父类的,还可以自己扩展,还可以改 -- 方法重写
	// 要求:子类要有足够的权限 + 方法声明和父类一样
	public void eat() {
		// 4.验证:重写后,对原来父类的功能,有影响吗? -- 没有,遵循OCP原则
		// super.eat();
		System.out.println("吃 猪肉");
	}
	
	// 2.子类除了能用父类的,还可以自己扩展
	public void coding() {
		System.out.println("敲代码");
	}
}

(3) 继承里的构造方法

package com.java.test;

// 测试 继承里的构造方法
// 总结:
// 1.构造方法的作用是:用来灵活的new 
// 2.继承后,子类构造方法里会隐藏 super() -- 意思是会自动调用父类的无参构造
// 3.如果父类没给无参构造,子类只能调用父类的含参构造
public class Tset01{
	public static void main(String[] args) {
		new Zi();
	}
}

class Fu{
	//TODO
	public Fu() {
		System.out.println(1);
	}
	
	public Fu(int a) {
		System.out.println(100);
	}
}

class Zi extends Fu{
	public Zi() {
		// 1.构造方法里,隐藏了super(),会自动调用父类的,无奈的构造方法
		// 3.super关键字,如果出现在了构造方法里,必须是第一条语句
		// super
		super(666);  // 2.触发的是父类的含参构造方法
		System.out.println(2);
	}
}

6.多态(多态只能调用父类中有的)

6.1 多态概念

(1) 多态是指同一个对象,在不同时刻表现出来的不同形态;

(2) 多态的前提(前提是有继承和重写)

  • 要有继承或者实现关系;
  • 要有方法的重写;
  • 要有父类引用指向子类对象,如: Animal(父类) a = new Dog()(子类);(小到大,向上转型)

(3) 创建多态对象口诀:

  • 口诀1:父类引用 指向 子类对象 —— 只能用父类的功能;
  • 口诀2:编译看左边(父类),运行看右边(子类)(针对方法);

6.2 多态中的成员访问特点

  • 成员变量 —— 编译看父类,运行看父类(使用的是父类的);
  • 成员方法 —— 编译看父类,运行看子类(由于存在重写现象,所以使用子类的);
  • 静态成员 —— 随着对象而存在,谁调用就返回谁的;

6.3 多态入门案例:

package com.java.test;

// 测试 多态(前提是有继承和重写)
public class Tset01{
	public static void main(String[] args) {
		// 创建子类对象测试 -- 可以用父类的,也可以用自己扩展的,也可以改父类的
		Dog d = new Dog();
		d.eat();
		// 创建多态对象 -- 口诀1:父类引用指向子类对象;-- 只能用父类的功能
		Animal a = new Dog();  // 1.统一调用的标准是父类;  2.通用性
		// 口诀2:编译看左边,运行看右边 -- 针对的是方法
		// System.out.println(a);  // 会输出a的地址值
		// 调用父类的eat() -- 统一调用标准,向父类看齐
		a.eat();  // 调用父类的方法声明,使用了子类的方法体
		System.out.println(a.age);
		// System.out.println(a.name);  // 多态对象不支持用子类的name
		
		// 专门使用子类的扩展资源? -- 不能用多态的对象(直接创建子类对象就可以)
		Dog d2 = new Dog();
		System.out.println(d2.name);
		
		// 向下转型
		Animal a2 = new Dog();  // 向上转型
		Dog d3 = (Dog) a2;  // 向下转型
		System.out.println(d3.name);
	}
}

// 创建父类 -- 可以提取子类的所有共性代码,提高了复用性
class Animal{
	int age = 10;
	public void eat() {
		System.out.println("啥都吃");
	}
}

// 创建子类 -- 可以使用父类的功能,减少了子类的代码量
class Dog extends Animal{
	String name = "苹果";  // 多态不支持用子类的,只支持父类的
	// 3.什么时候需要重写:当子类想要修改父类原来的功能时
	@Override  // 重写方法的标记 -- 注解
	public void eat() {
		System.out.println("够吃饭");
	}
}

/**
* 打印结果:
* 够吃饭
* 够吃饭
* 10
*/

6.4 多态的好处和弊端

(1) 好处:提高了程序的扩展性和维护性,多态可以让我们不用关心某个对象到底是什么具体类型,就可以使用该对象的某个方法;

(2) 弊端:不能使用子类的特有成员;

6.5 多态的使用:

package com.java.test;

// 测试 多态的使用
public class Tset01{
	public static void main(String[] args) {
		// 口诀1:父类引用指向子类对象
		Fu f = new Zi();
		
		// 口诀2:编译看左边(只能调用父类的),执行看右边(若方法被重写,执行子类方法体)
		System.out.println(f.age);  // 使用了父类的10
		f.eat();  // 2.重写了,使用父类方法声明和子类方法体
		f.sleep();  // 没重写,使用父类方法声明和方法体
		// f.show();  // 这里的show是子类扩展的多态对象,不能用子类扩展的
		f.game();  // 4.使用了父类的
		Fu.game();
	}
}

// 成员变量 / 方法 / 静态资源
class Fu{
	// 成员变量
	int age = 10;
	
	// 静态资源 -- 静态资源不能被重写,但可以继承
	static public void game() {
		System.out.println(66);
	}
	
	// 成员方法
	public void eat() {
		System.out.println(1);
	}
	
	public void sleep() {
		System.out.println(2);
	}
}

class Zi extends Fu{
	int age = 20;
	static public void game() {
		System.out.println(2);
	}
	
	@Override //方法重写
	public void eat() {
		System.out.println(100);
	}
	
	public void show() {
		System.out.println(200);
	}
}

6.6 多态中的转型:

(1) 向上转型:父类引用指向子类对象,就是向上转型(如: Parent p = new Child() );

(2) 向下转型: 格式 子类型 对象名 = (子类型) 父类引用;

(3) 多态转型案例:

package com.java.test;

// 测试 多态的转型
public class Tset01{
	public static void main(String[] args) {
		// 多态 -- 向上转型
		Animal a = new Cat();
		a.eat();
		// a.playGame();
		// 向下转型
		Cat c = (Cat) a;
		c.eat();
		c.playGame();
	}
}

// 父类 -- 动物类
public class Animal{
	public void eat() {
		System.out.println("动物吃东西");
	}
}

// 子类 -- 猫类
public class Cat extends Animal{
	@Override
	public void eat() {
		System.out.println("猫吃鱼");
	}
	
	public void playGame() {
		System.out.println("捉迷藏");
	}
}

(4) 向上转型和向下转型

      ① 在应用中,存在着两种转型方式,分别是向上转型和向下转型;

      ② 向上转型:父类的引用指向子类对象 (Parent p = new Child; → 多态)
        说明:向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类的方法,就根据这个引用指向调用子类重写方法;

      ③ 向下转型(较少):子类对象的引用指向子类对象,过程中必须采取到强制转型:
        例:

Parent P = new Child();
Child C = (Child) P;  // 此时,把Parent 类型的P转成小类型的Child

// 其实,相当于创建了一个子类对象一样,可以用父类的,也可以用自己的

说明:向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做个功能拓展,就可以直接使用子类功能;

============================================

7.面向对象 总结:

  • 哪些资源不能被继承? – private 私有的 / 构造方法
  • 哪些资源不能被重写? – static 静态的 / final / private / 构造方法
  • 多态怎么统一的调用标准? – 只能调用父类的
  • 怎么使用子类特有的? – 多态对象不支持,只能new一个子类对象
  • 多态有什么好处?
      a.增强程序的通用性、统一标准;
      b.多态根本不关心具体的子类类型,屏蔽掉了子类之间的不同,把子类当父类来看;

============================================

8.抽象类 abstract

8.1 抽象类概念:

  • Java中,可以定义没有方法体的方法,这个没有方法体的方法,我们称之为抽象方法,含有抽象方法的类,我们称之为抽象类;

8.2 抽象类的特点

(1) 抽象类和抽象方法必须使用abstract 关键字修饰,所以可以修饰方法和类;

      ① 抽象类的定义: public abstract class 类名{};

      ② 抽象方法的定义: public abstract void eat();

(2) 抽象类中可以没有抽象方法(由子类去实现),有抽象方法的类一定是抽象类;

(3) 子类继承了抽象类以后,要么还是一个抽象类,要么就把所有抽象方法都重写;

(4) 多用于多态中;

(5) 抽象类不可以被实例化(就是不能被直接new):抽象类如何实例化呢?参照多态的方式,通过子类对象实例化,这叫做抽象类多态;

(6) 抽象类的成员特点

成员变量既可以是变量,也可以是常量
构造方法空参构造
有参构造
成员方法抽象方法
普通方法

8.3 抽象类入门案例

package com.java.test;

// 测试 抽象类 abstract
public class Test{
	public static void main(String[] args) {
		// 第三步 创建多态的对象
		// Fu2 a = new Zi2;  // 抽象类不可以被实例化
		Fu2 a = new Zi3;
		a.eat();
		a.game();
	}
}

// 第二步 创建父类 -- 设计成抽象类
abstract class Fu2{
	// 3.抽象类是一个特殊的类? -- 因为抽象类里可以包含抽象方法和普通方法
	// 2.如果一个类里包含着抽象方法,那么这个类必须设计成抽象类
	// 1.抽象方法:没有方法体,被abstract 修饰
	abstract public void eat();
	
	// 普通方法
	public void game() {
		System.out.println("啥都玩");
	}
}

// 第三步 创建子类 -- 继承抽象类
class Zi3 extends Fu2{
	// 2.子类继承了抽象的父类,需要重写父类里面所有的抽象方法
	@Override
	public void eat() {
		System.out.println(1);
	}
}

abstract class Zi2 extends Fu2{
	// 子类继承了抽象的父类,会把抽象方法继承过来,此时子类包含着继承来的抽象方法,必须定义一个抽象的子类,不然只能重写;
}

8.4 抽象类的使用

package com.java.test;

// 测试 抽象类 abstract 的使用
public class Test{
	public static void main(String[] args) {
		Fu3 f = new Zi4();
		f.name = "rose";  // 改变了变量的值
		System.out.println(f.name);  // 打印改了变量的值
		System.out.println(Fu3.AGE);  // 打印改了常量的值
	}
}

// 提供抽象类
abstract class Fu3{
	//TODO Constructor(构造方法)
	// 1.提供抽象类里有构造方法吗? -- 有,不是为了自己new,而是为了子类new
	public Fu3(){
		System.out.println("这是构造方法,用来new");
	}
	
	// 2.1 抽象类里有成员变量吗? 有
	String name = "jack";
	
	// 2.2 抽象类里有常量吗? 有
	public static final int AGE = 10;  // 常量的标准写法
	// final int age = 10;  // 常量的简写
	
	// 3.抽象类 里有普通方法吗? 抽象方法吗?
	abstract public void eat1();  // 抽象方法没有方法体;
	abstract public void eat2();  // 抽象方法没有方法体;
	public void eat3() {
		System.out.println(3);
	}
}

// 4.子类继承了抽象的父类后,需要重写所有的抽象方法,否则是一个抽象类
class Zi4 extends Fu3{
	// 什么都不写时,里面隐藏着一个无参的构造方法
	// public Zi4(){
	//     super();  // 自动调用父类的 无参构造方法
	// }
	public Zi4() {
		super();
		System.out.println("这是子类的构造方法,用来new");
	}
	
	// 重写父类里面的抽象方法
	@Override
	public void eat1() {
		System.out.println("重写方法1");
	}
	public void eat2() {
		System.out.println("重写方法2");
	}
}

8.5 抽象类的用法

8.5.1 构造函数

(1) 抽象类也有构造方法,但是不能实例化;一般用于给子类实例化new的;

package com.java.test;

// 抽象类的构造方法
public class Test{
	public static void main(String[] args) {
		// Animal2 a2 = new Animal2();  // 抽象类无法实例化,只能用多态
		// Zi2 z = new Zi2();  // 创建子类实例化对象
		Animal2 a2 = new Zi2();  // 抽象类多用于多态;
	}
}

public class Test2_Animal2{}

abstract class Animal2{
	// 抽象类可以有构造方法,但是无法实例化,用于子类实例化
	public Animal2() {
		System.out.println("fu.Animal2()");
	}
}

class Zi2 extends Animal2{}

9.接口 - interface

9.1 继承、接口关系示意图;

继承、接口关系示意图

9.2 接口概念:

(1) 接口定义:

  • 接口是抽象类的延伸,可以将它看作是纯粹的抽象类,接口中所有的方法都没有方法体;
  • 接口就是一种公共的规范标准,只要符合规范标准,大家都可通用;
  • Java中的接口更多的体现在对行为的抽象;
  • Java里面由于不允许多重继承,所以如果要实现多个类的功能,则可以通过实现多个接口实现;

(2) 接口语法

接口语法
释义:

  • public:接口可以像类一样被权限修饰符修饰,但public关键字仅限于接口在与其同名的文件中被定义;
  • 在接口中,方法必须被定义为public或abstract形式;
  • 在接口中,定义的任何字段都自动是 static 和 final 的;

9.3 接口特点

(1) 接口中都是抽象方法;

(2) 通过interface关键字创建接口;

(3) 通过implements (实现)让子类来实现;

实现语法

(4) 可以理解成,接口是一个特殊的抽象类。

(5) 接口突破了Java的单继承的局限性;

(6) 接口和类之间可以多实现,接口和接口之间可以多继承;

(7) 接口是对外暴露的规则,是一套开发规范;

(8) 接口提高了程序的功能扩展,降低了耦合性;

(9) 接口不能实例化;

  • 接口如何实例化呢? – 参照多态的方式,通过实现类对象实例化,这叫接口多态;
  • 多态的形式:具体类多态,抽象类多态,接口多态;

(10) 接口的子类:

      ① 要么重写接口中所有抽象方法;

      ② 要么子类也是抽象类;

(11) 接口的成员特点:

      ① 成员变量 – 接口没有变量,只有常量,默认修饰符:public static final

      ② 构造方法 – 接口没有构造方法,因为接口主要是扩展功能的,而没有具体存在;

      ③ 成员方法 – 接口只能是抽象方法,默认修饰符: public abstract

9.4 接口代码:

(1) 入门案例:

在这里插入代码片

(2) 测试接口

在这里插入代码片

(3) 接口的用法:

在这里插入代码片

(4) 接口的复杂使用:

在这里插入代码片

六、关键字

1.this关键字

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

(2) this 代表本类对象的一个引用对象,在构造方法中,this() 必须放在第一行:

  • 是一个类里的现象
  • 互相调用,本类的资源,可以使用this,通常可以省略不写;
  • 两种情况必须写 this,当变量名相同时 + 构造方法调用时;

(3) this 关键字测试

package com.java.test;

// 测试 this 关键字
/**
 * 总结
 * 1.this 代表本类对象的一个引用,相当于this帮你创建了一个本类的对象
 * 2.this 可以调用同一个类里的所有资源(成员变量/方法/构造方法)
 * 3.this 使用的第一个场景是:用来区别同名的成员变量和局部变量,this调用的
 * 4.this 使用的第二个场景是:用来在构造方法间相互调用
 * 5.位置必须是第一条语句+不能形成类似于死循环的样子
 */
public class Tset01{
	public static void main(String[] args) {
		// new Animal().eat();
		new Animal();
	}
}

class Animal{
	//TODO Constructor
	public Animal() {
		// 在无参构造中调用含餐构造
		this("Jack");   // 构造方法里,如果出现this,必须是第一条语句
		System.out.println("无参 构造方法");
	}
	
	public Animal(String b) {
		System.out.println("含参 构造方法" + b);
	}
	
	public Animal(int a) {
		// 3.在含参构造中,调用 无参构造
		this();
		System.out.println("含参 构造方法" +a );
	}
	
	//TODO Field 成员变量
	String name = "rose";
	
	//TODO Method 成员方法
	public void eat() {
		String name = "Jack";
		// 1.变量使用就近原则,优先使用局部变量,Jack
		System.out.println(name);
		// 2.this底层帮你创建了本类对象,相当于 Animal this = new Animal();
		
		// this 代表本类对象的一个引用,this的场景1;
		// this 的场景1:当局部变量名和 成员变量名相同时,通过 this调用成员变量
		System.out.println(this.name);
		System.out.println("吃s");
	}
}

2.super 关键字

(1) 概述

  • super 表示父类对象的一个引用(this 则代表本类对象的引用);
  • 在子类中用,用来调用父类的功能;
  • 和this一样,如果出现在了构造方法里,必须是第一条语句;

(2) this 和 super 的使用区别

关键字访问成员变量访问构造方法访问成员方法
thisthis.成员变量:
访问本类成员变量
this(…):
访问本类构造方法
this.成员方法(…):
访问本类成员方法
supersuper.成员变量:
访问父类成员变量
super(…):
访问父类的构造方法
super.成员方法(…):
访问父类成员方法
  • this 代表本类对象的引用,super代表父类对象的引用;
  • this 用于区分局部变量和成员变量;
  • super 用于区分本类变量和父类变量;
  • super.成员变量 / super.成员方法() / super([参数]),代表调用父类内容
  • this.成员变量 / this.成员方法() / this([参数]),代表调用父类内容
  • this和super不可以同时出现在同一个构造方法里,它们两个只要出现都必须放在第一行,所以不能同时出现;

3.static – 静态资源耗内存,谨慎使用

3.1 static概念:

  • static是Java中的一个关键字,静态的意思,用于修饰成员方法,成员变量;

3.2 static特点:

  • 可以修饰成员变量、成员方法;
  • 随着类的加载而加载,优先于对象加载;
  • 只加载一次,就会一直存在,不在开辟新空间;
  • 全局唯一,全局共享,被类的所有对象共享 —— 这也是我们判断是否使用静态关键字的条件;
  • 可以直接被类名调用,也可以通过对象名调用;(推荐使用类名调用)

3.3 测试static关键字

package com.java.test;

// 测试 static关键字
public class Tset01{
	public static void main(String[] args) {
		// 创建对象测试 new
		Person p = new Person();
		p.eat();
		System.out.println(p.age);
		p.sleep();
		System.out.println(p.name);
		
		// 1.如果资源是static资源,可以通过对象访问+类名访问
		// 2.通过静态的方式访问,即通过类名直接调用(普通资源,绝对不能通过类名直接调用)
		Person.sleep();
		System.out.println(Person.name);
		
		Person p1 = new Person();
		p1.name = "快乐星球";
		
		Person p2 = new Person();
		System.out.println(p2.name);
		
		Person p3 = new Person();
		System.out.println(p3.name);
		
		Person p4 = new Person();
		System.out.println(p4.name);
	}
}

class Person{
	// 普通资源
	int age = 10;
	public void eat() {
		// 普通资源可以调用所有资源
		System.out.println(name);
		System.out.println(1);
	}
	
	// 静态资源 static
	// 1.static可以修饰成员变量和方法
	// 2.static资源优先于对象的加载
	// 3.static资源是共享的,可以直接被类名调用
	static String name = "tony";
	static public void sleep() {
		// 4.静态只能调用静态、非静态,可以随意调用
		// 静态不能直接调用普通资源,必须修饰成static的
		System.out.println(2);
	}

}

3.4 静态代码块、构造代码块、局部代码块

3.4.1 静态代码块

(1) 静态代码块 概述:
      ① 静态代码块:在类加载时就加载,并且只被加载一次,一般用于项目的初始化;

      ② 构造代码块:在调用构造方法前会自动调用,每次创建对象都会被调用;

      ③ 局部代码块:方法里的代码块,方法被调用时才会执行;

      ④ 静态代码块:

           a. static{} – 位置:类里方法外;

           b.在类第一次加载时就加载到内存中并一直驻存;并且全局共享,直到类消失,静态资源才消失;

           c.静态资源只被加载一次;

(2) 测试(执行顺序:静态代码块 → 构造代码块 → 构造函数)

package com.java.test;

// 测试 static 静态代码块
public class Tset01{
	public static void main(String[] args) {
		new Student();
	}
}

class Student{
	// 静态代码块
	static {
		System.out.println("静态代码块");
	}
	
	// Constructor 构造方法
	public Student() {
		System.out.println("构造方法");
	}
	
	// 构造代码块
	{
		System.out.println("构造代码块");
	}
	
	// 局部代码块
	public void show() {
		System.out.println("局部代码块");
	}
}

4.final:用来约束父类资源的重写权限

4.1 概念

(1) 状态修饰符:

  • final:最终态;
  • static:静态

(2) final:是Java关键字,是最终的意思,可以修饰成员方法、成员变量、类;

(3) final 修饰的特点:
      ① 修饰方法:表明该方法是最终方法,不能被重写;

      ② 修饰变量:表明该变量是常量,不能再次被赋值;

      ③ 修饰类:表明该类是最终类,不能被继承;

      ④ 常量的定义形式: final 数据类型 常量名 = 值;

(4) final 修饰局部变量:
      ① 变量是基本类型:final 修饰指的是基本类型的 数据值 不能发生改变;

      ② 变量是引用类型:final修饰指的是引用类型的 地址值 ,不能发生改变,但是地址里面的内容是可以发生改变的;

4.2 final 入门案例

package com.java.test;

// 测试 final关键字 —— 可以修饰类、方法、变量
public class Tset01{
	public static void main(String[] args) {
		Zi z = new Zi();
		z.eat();
		System.out.println(z.name);
	}
}

class Fu{
	// 被final修饰的类,不能被继承
	// 被final修饰的变量是个常量,不能被更改
	final String name = "Jack";
	// 被fianl修饰的方法,不能被重写
	final public void eat() {
		System.out.println(1);
	}
}

八、核心API

1.API 定义:

============================================

2.常用类:

2.1 顶级父类 Object

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.2 String 字符串对象

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.3 StringBuilder / StringBuffer

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.4 包装类 – 涉及到集合

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.5 日期类 Date

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.6 日期工具 SimpleDate Format

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

2.7 BigDecimal / BigInteger

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

============================================

3.IO流:

============================================

4.泛型 Generics:

============================================

5.集合:

5.1 集合概念:

(1) 集合定义:集合可以看作是一个容器,提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变;

(2) 常用的集合有 List 集合,Set 集合和 Map集合,其中List与Set继承了Collection接口,各接口还提供了不同的实现类;

(3) 常用集合类的继承关系:

常用集合类的继承关系
(4) 集合类和数组的区别:

      ① 数组的长度是固定的,集合的长度是可变的;

      ② 数组用来存放基本类型的数据,集合用来存放对象的引用;

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

5.2 Collection 集合 接口:

(1) 概述:

  • Collection 接口是层次结构中的根接口,构成Collection的单位(对象),称为元素;一些Collection允许有重复的元素,而另一些则不允许。一些Collection 是有序的,而另一些则是无序的;
  • Collection 接口通常不能直接使用,但该接口提供了添加元素、删除元素、管理数据的方法;

(2) 集合的继承结构:

集合的继承结构
      ① Collection 是父接口;

      ② 学习方法:

          创建对象:学习底下的实现类怎么用;
          常用方法:学习上面的接口(即抽象层);

(3) Collection 接口的常用方法:

方法功能描述
boolean add(E e)添加元素
boolean addAll(Collection c)把小集合添加到大集合中
boolean contains(Object o)如果此 Collection包含指定的元素,则返回 true
boolean isEmpty()如果此 Collection没有元素,则返回 true
Iterator iterator返回在此 Collection 的元素上进行迭代的迭代器
boolean remove(Object o)从此 Collection中移除指定元素的单个实例
int size()返回此Collection 中的元素数
Object[] toArray()返回对象数组

(4) 练习1:测试 Collection 接口的常用方法:

package com.java.test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

// 测试 Collection
public class Test{
	public static void main(String[] args) {
		// 1.创建对象 c
		Collection<Integer> c = new ArrayList<>();  // 接口不能直接 new,需要new它的子类;
		
		// 2.调用方法
		// (1)boolean add(E e) -- 向集合中添加元素(int 类型给Integer类型没报错的原因是自动装箱)
		c.add(100);
		c.add(200);
		c.add(300);
		System.out.println(c);
		
		//(2)void clear()  -- 清空集合(一般不用)
		// c.clear();
		
		// (3)boolean contains(Object o)  -- 判断c里面是否包含“200”这个元素
		System.out.println(c.contains("200"));
		
		// (4)boolean equals(Object o)  -- 判断c这个集合是否与“Jack”相等
		System.out.println(c.equals("Jack"));
		
		// (5)int hashCode()  -- 获取哈希码值
		System.out.println(c.hashCode());
		
		// (6)boolean isEmpty()  -- 判断c是否为空
		System.out.println(c.isEmpty());
		
		// (7)boolean remove(Object o)  -- 移除“100”元素
		System.out.println(c.remove(100));
		
		// (8)int size()  -- 获取集合中元素的个数
		System.out.println(c.size());
		
		// (9)Object[] toArray()  -- 把c里的数据存入数组 Object[] 中(因为Object[] 可以存的数据类型丰富,很通用)
		Object[] o = c.toArray();
		System.out.println(Arrays.toSting(o));
		
		// (10)方式一:Iterator<E> interator -- 用来迭代集合中的元素(Iterator迭代器)
		Iterator<Integer> it = c.iterator();
		while(it.hasNext()) {  // 判断条件:有数据就取,没数据就结束(方法 hasNext()是判断有没有数据)
			Integer data = it.next();  // 获取数据
			System.out.println(data);
		}
		
		// (11)方式二:foreach 的使用场景:数组 / Collection集合
		for(Integer z : c) {  // foreach可以快速的迭代集合
			System.out.println(z);
		}
		
		// 创建对象 c2
		Collection<Integer> c2 = new ArrayList<>();
		c2.add(100);
		c2.add(200);
		c2.add(300);
		
		// 下面这四个是集合间的操作,了解即可
		// ()boolean addAll(Collection<? extend E> c)
		System.out.println(c.addAll(c2));  // 把c2加到c里
		System.out.println(c);  // [200,300,100,200,300]
		
		// ()boolean containsAll(Collection<?> c)
		System.out.println(c.containsAll(c2));  // 判断c里包含c2吗
		
		// ()boolean removeAll(Collection<?> c)
		// System.out.println(c.removeAll(c2));  // 移除c和c2的交集
		
		// ()boolean retainAll(Collection<?> c)
		System.out.println(c.retainAll(c2));  //保留c和c2里的交集元素
		System.out.println(c);
	}
}

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

5.3 List集合 接口 interface:

(1) 概述:

      ① List 集合包括List接口以及List接口的所有实现类;

      ② List接口概述:

          a. 有序,有索引,可以重复;

          b. 可以根据索引查询/插入/删除/修改;

          c. 是一个Collection的子接口,因此继承了Collection接口中的所有方法,可以用父接口的功能,也可以扩展;

      ③ List接口的常用实现类有ArryList和LinkedList;

(2) List接口自己扩展的方法:

方法名作用
void add(int index,E element)在列表的指定位置插入指定元素(可选操作);
boolean addAll(int index,Collection<? extends E> c)将指定Collection中的所有元素都插入到列表中指定位置(可选操作);
E get (int index)返回列表中指定位置的元素;
int indexOf(Object o)返回此列表中第一次出现的指定元素的索引;
int lastIndexOf(Object o)返回此列表中最后出现的指定元素的索引;
ListInterator listInterator()返回此列表元素的列表迭代器(按适当顺序排序)
ListIntor listIterator(int index)返回列表中元素列表迭代器(按适当顺序),从列表的指定位置开始;
E remove (int index)移除列表中指定位置的元素(可选操作);
E set(int index,E element)用指定元素替换列表中指定位置的元素(可选操作);
List subList(int fromIndex,int toIndex)返回列表中指定的fromIndex(包括)和toIndex(不包括)之间的部分视图;

(3) 测试List接口常用方法:

package com.game.nn;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

// 测试 List接口
public class Test {
    public static void main(String[] args) {
        // 1.创建对象
        List<Integer> list = new ArrayList<>();

        // 2.调用方法
        // boolean add(E e)
        list.add(100);
        list.add(200);
        list.add(300);
        list.add(200);
        list.add(null);
        list.add(null);

        System.out.println(list);  // [100,200,300,200,null,null]

        // 继承自父接口Collection

        // void clear
        // boolean contains(Object o)
        // boolean containsAll(Collection<?> c)
        // boolean equals(Object o)
        // int hashCode

        // 自己扩展的方法
        // void add(int index,E element)   // 在指定下标位置添加新元素
        list.add(1,10);
        System.out.println(list);

        // E get(int index)  // 获取下标为3对应的元素
        System.out.println(list.get(3));

        // int indexOf(Object o)  // 获取"200"这个元素第一次出现的下标值
        System.out.println(list.indexOf(200));

        // int lastIndexOf(Object o)  //获取"200"这个元素最后一次出现的下标值
        System.out.println(list.lastIndexOf(200));

        // E remove(int index)  // 移除“1”下标处的元素,并将该元素返回
        System.out.println(list.remove(1));

        // E set(int index,E element)  // 把“5”下标处的元素换成666,并将原先那个元素返回
        System.out.println(list.set(5,666));
        System.out.println(list);

        // list<E> subList(int fromIndex,int toIndex)
        // 从下标“2”开始到下标“4”结束,截取了[2-4)的元素,不包含下标“4”的元素
        List<Integer> list2 = list.subList(2,4);
        System.out.println(list2);

        // 移除指定元素 [10,200,300,200,null,666]
        // System.out.println(list.remove(2));  // 按下标移除
        System.out.println(list.remove(new Integer(300)));  // 直接移除元素
        System.out.println(list);

        // 迭代List接口中的元素方式
        // 方式1:继承自父接口的方法 Iterator<E> iterator
        Iterator<Integer> it = list.iterator();
        while(it.hasNext()){  // 判断有没有元素
            Integer data = it.next();  // 获取元素
            System.out.println(data);
        }
        
        // 方式2:List有下标,根据下标遍历for
        for (int i = 0; i < list.size(); i++) {
            Integer data = list.get(i);  // 根据下标获取元素
            System.out.println(data);
        }
        
        // 方式3:foreach
        for (Integer x : list) {
            System.out.println(x);
        }
        
        // 方式4:List子接口的扩展方法ListIterator<E> listIterator()
        ListIterator<Integer> it2 = list.listIterator();
        
        // 顺序遍历
        while(it2.hasNext()){  // 判断有没有元素
            Integer data = it2.next();  // 获取元素
            System.out.println(data);
        }
        
        // 逆向遍历
        while(it2.hasPrevious()){
            Integer data = it2.previous();
            System.out.println("data=" + data);
        }
    }
}

(4) 并发修改异常 ConcurrentModificationException

      ① 产生原因:迭代器遍历的过程中,通过集合对象修改了集合中的元素,造成了迭代器获取元素中判断预期修改值和实际修改值不一致;

      ② 解决方案:用for循环遍历,然后用集合对象做对应的操作即可;

(5) ListIterator —— 列表迭代器

      ① ListIterator列表迭代器定义:

  • 通过List集合的 ListIterator() 方法得到,所以说它是List集合特有的迭代器;
  • 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表并获取列表中迭代器的当前位置;

      ② ListIterator 中常用的方法

常用方法说明
E next()返回迭代中的下一个元素
boolean hasNext()如果迭代具有更多元素,则返回true
E previous返回列表中的上一个元素
boolean hasPrevious()如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true
void add(E e)将指定的元素插入列表

(6) 数据结构:是计算机存储、组织数据的方式,是指相互之间存在一种或多种特定关系的数据元素的集合;

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

5.4 ArrayList 实现类

(1) ArrayList类实现了可变的数组,允许保存所有元素,包括null,并可以根据索引位置对集合进行快速的随机访问;

缺点:是向指定的索引位置插入对象或删除对象速度较慢;

  • ArrayList 存在于Java.util包中,底层是数组;
  • 内部用数组存放数据,封装了数组的操作,每个对象都有下标;
  • 内部数组默认初始容量是10,如果不够会1.5倍容量增长;
  • 查询快,增删数据效率会降低;

(2) 创建对象-调用对象:

List<E> list = new ArrayList<>();
new ArrayList();

注意:E可以是合法的Java数据类型;例如:字符串类型,那么E可以修改为String;

(3) 练习1:测试ArrayList接口常用方法:

package com.game.nn;

import java.util.ArrayList;
import java.util.Arrays;

// 测试 ArrayList接口常用方法
public class Test {
    public static void main(String[] args) {
        // 1.创建对象
        // 本质上底层会维护一个数组 Object[] elementData,用来存入ArrayList中的数据
        // JDK1.6版本中 -- 当创建ArrayList对象时,底层会初始化一个数组,默认容量是10;
        // 数据多的时候,超过10个时,会自动扩容:旧容量+ 旧容量/2
        // JDK1.8版本中 -- 但是一开始是一个空数组,当第一次添加数据时,才会自动扩充容量
        ArrayList<String> list = new ArrayList<>();
        
        // 2.调用方法
        // 2.add被调用时,拿着数据,直接存入了Object[] 中
        list.add("1");  // 存入数组里的0下标处
        list.add("2");  // 存入数组里的1下标处
        list.add("3");
        list.add("1");
        list.add(null);
        
        // 特点:有序+右下标+可重复
        System.out.println(list);
        
        // 继承自Collection接口的
        // 继承自 List接口的
        // 模拟ArrayList
        // 创建对象时,会创建数组并初始化
        Object[] elementData = {};  // 1.8的写法
        elementData = new Object[10];  // 1.6的写法
        
        // add() 添加数据时,把数据存入数组里
        elementData[0] = "1";
        elementData[1] = "2";
        elementData[2] = "3";
        elementData[3] = "4";
        
        // 数组的长度 <=10时,不会扩容; >10时,会自动扩容,是以前的1.5倍;
        elementData = Arrays.copyOf(elementData,15);
        elementData = Arrays.copyOf(elementData,22);
    }
}

(4) 练习2:求List里的偶数和,奇数个数、平均值;

package com.game.nn;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

// 集合的工具类 Collections -- addAll
public class Test {
    public static void main(String[] args) {
        // 求List里的偶数和、奇数个数、平均值
        method();
        method2();
    }
    
    public static void method(){
        List<Integer> list = new ArrayList<>();
        
        // 利用工具类,一次性向集合中添加一批数据
        Collections.addAll(list,1,4,2,74,6,89,56);
        System.out.println(list);
        
        // 利用工具类,获取最大值max,最小值min
        Integer max = Collections.max(list);
        System.out.println(max);
        Integer min = Collections.min(list);
        System.out.println(min);
        
        // sort() 升序排序
        Collections.sort(list);
        System.out.println(list);
    }
    
    public static void method2(){
        List<Integer> list = new ArrayList<>();
        // 利用工具类,一次性向集合中添加一批数据
        Collections.addAll(list,3,4,2,66,3,39,57);
        
        // 练习:求List里的最大值,最小值
        // 迭代集合 foreach
        int sum = 0;  // 定义变量,记录偶数和
        int count = 0;  // 定义变量,记录奇数和;
        int all = 0;  // 定义变量,记录总和
        for (Integer data : list) {
            all = all + data;
            if(data % 2 == 0){  // 过滤偶数
                System.out.println(data);
                sum = sum + data;  // 求和
            }
            if(data % 2 == 1){
                count++;  // 个数+1
            }
        }
    }
}

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

5.5 LinkedList 实现类

(1) 概述:

  • LinkedList实现类,采用链表结构保存对象,适合增删业务;
  • LinkedList实现类是List接口实现类,可以使用List接口的所有方法,也可以扩展;
  • 示意图:

LinkedList实现类
(2) LinkedList实现类常用方法:

方法名说明
public void addFirst(E e)在该列表开头插入指定的元素
public void addLast(E e)将指定的元素追加到此列表的末尾
public E getFirst()返回此列表中的第一个元素
public E getLast()返回此列表中的最后一个元素
public E removeFirst()从此列表中删除并返回第一个元素
public E removeLast()从此列表中删除并返回最后一个元素

(3) 创建对象:List list = new LinkedList<>();

(4) List集合中子类ArrayList,LinkedList对比

      ① ArrayList:底层数据结构是数组,查询快,增删慢;是连续空间,适合查询业务;
ArrayList

      ② LinkedList:底层数据结构是链表,查询慢,增删快;适合增删业务;

LinedList
(5) 测试LinkedList接口

package com.game.nn;

import java.util.Collections;
import java.util.LinkedList;

// 测试 LinkedList
public class Test {
    public static void main(String[] args) {
        // 创建对象
        LinkedList<Integer> list = new LinkedList();

        /**
         * 调用方法:
         * 继承自 Collection 接口的方法们
         * 继承自 List接口的方法们
         */
        // 扩展的方法们
        Collections.addAll(list,1,2.3,4,5);
        list.addFirst(100);  // 添加首元素
        list.addLast(300);  // 添加尾元素
        list.getFirst();  // 获取首元素
        list.getLast();  // 获取尾元素
        list.removeFirst();  // 删除首元素
        list.removeLast(); // 删除尾元素
        System.out.println(list);
        
    }

}

♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡

5.6 Set集合

(1) Set集合概述:Set集合中由Set接口和Set接口的实现类组成;

(2) Set集合的特点:

  • 不包含重复元素的集合;
  • 没有带索引的方法,所以不能使用普通for循环遍历;

(3) Set接口概述:

  • Set接口特点:不重复 + 无序 + 没下标 + 只存一个null;
  • Set接口继承了Collection接口,可以使用父接口的所有方法,也可以扩展(Set没扩展);
  • Set接口没法new,所以只能学习方法;
  • Set接口常用的实现类有HashSet类和TreeSet类;

(4) Set集合特点:

      ① 哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的值;

          a. Object 类中有一个方法可以获取对象的哈希值:public int hashCode() // 返回对象的哈希值;

          b. 对象哈希值特点:

              同一个对象,多次调用 hashCode()方法返回的哈希值是相同的;

              默认情况下,不同对象的哈希值是不同的,而重写hashCode()方法,可以实现让不同对象的哈希值相同;

      ② HashSet类:实现Set接口,底层是哈希表,包装了HashMap,相当于像HashSet中存入数据时,会把数据作为K,存入内部的HashMap中(当然K不许重复),可以使用Set接口的方法们,也可以扩展;

          a. HashSet实现类,可以学习的是new,方法都是实现来的;

          b. HashSet创建对象 —— HashSet();

              构造一个新的空 set,其底层是HashMap实例的默认初始容量是16,加载因子是0.75(意思是,当空间使用达到16×0.75时,会自动扩容);

      ③ TreeSet 类底层就是TreeMap,也是红黑树的形式,便于查找数据;(TreeSet 类不仅实现了Set接口,还实现了java.util.SortedSet接口,因此,TreeSet类实现的Set集合在遍历集合时按照自然顺序递增排序,也可以按照指定比较器递增排序;)

          a. TreeSet 类增加方法:

方法功能描述
first()返回此Set中当前第一个最低元素;
last()返回此Set中当前最后一个最高元素;
comparator()返回此Set中的元素进行排序的比较器,如果此Set使用自然顺序,则返回null
headSet(E toElement)返回一个新的Set集合,新集合是toElement(不包含)之前的所有对象;
SubSet (E fromElement,E fromElement)返回一个新的Set集合,是fromElement(包含)对象与fromElement(不包含)对象之前的所有对象
tailSet (E fromElement)返回一个新的Set集合,新集合包含对象fromElement(包含)之后所有的对象

      ④ HashMap实现中,当哈希值相同的对象,会在同一个hash值的位置存储不同属性的数据;例如:

private transient HashMap<E,Object> map;

...

public boolean add<E e>{
      return map.put(e,PRESENT) == null;
}

(5) Set接口常用方法:


九、Java 高级语法

1.多线程

============================================

2.锁

============================================

3.设计模式

============================================

4.注解

============================================

4.反射

============================================


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值