Java学习笔记

1. Java入门

1.1 Java简介

Java最早是由SUN公司(已被Oracle收购)在上个世纪90年代初开发的一种编程语言,在1995年以Java的名称正式发布。随着互联网的高速发展,Java逐渐成为最重要的网络编程语言。

1.2 JVM

JVM(Java Virtual Machine),Java虚拟机。Java是将代码编译成一种“字节码”,它类似于抽象的CPU指令,然后,针对不同平台编写虚拟机,不同平台的虚拟机负责加载字节码并执行,这样就实现了“一次编写,到处运行”的效果。

1.3 JDK

JDK(Java Development Kit),Java语言开发工具包。

我们常用两个组件:

  • javac - 编译器,将源程序转成字节码
  • java - 运行编译后的.class文件

1.4 Java程序执行过程

image-20211201163510053

1.5 JRE

JRE(Java Runtime Environment),Java运行环境,简单来说,JRE就是运行Java字节码的虚拟机。但是,如果只有Java源码,要编译成Java字节码,就需要JDK,因为JDK除了包含JRE,还提供了编译器、调试器等开发工具。

1.6 Java的三个版本

  • Java SE:Standard Edition - 标准版,包含标准的JVM和标准库
  • Java EE:Enterprise Edition - 企业版,它只是在Java SE的基础上加上了大量的API和库,以便方便开发Web应用、数据库、消息服务等
  • Java ME:Micro Edition - 微型版,针对移动设备,目前主流是安卓开发,不建议学习。

三者之间的关系

┌───────────────────────────┐
│Java EE                    │
│    ┌────────────────────┐ │
│    │Java SE             │ │
│    │    ┌─────────────┐ │ │
│    │    │   Java ME   │ │ │
│    │    └─────────────┘ │ │
│    └────────────────────┘ │
└───────────────────────────┘

1.7 安装JDK

1.7.1 下载安装

官方下载地址

windows 64位jdk-17下载

默认安装即可

image-20211130081839913

安装完成后可以看到如下结构的目录

image-20211130082048776

1.7.2 配置环境变量

为了可以直接执行java命令,需要设置一个JAVA_HOME的环境变量,它指向JDK的安装目录。在Windows下,它是安装目录,类似:

C:\Program Files\Java\jdk-17.0.1

image-20211130082803664

然后,把JAVA_HOMEbin目录附加到系统环境变量PATH上。如下图:

image-20211130083157869

这是打开CMD输入java -version看到如下输出,就代表设置成功了。开启你的java变成之旅吧。

C:\Users\Administrator>java -version
java version "17.0.1" 2021-10-19 LTS
Java(TM) SE Runtime Environment (build 17.0.1+12-LTS-39)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.1+12-LTS-39, mixed mode, sharing)

其他系统可以参考java官方配置环境变量

bin目录下常用的可执行文件:

  • java:这个可执行程序其实就是JVM,运行Java程序,就是启动JVM,然后让JVM执行指定的编译后的代码;
  • javac:这是Java的编译器,它用于把Java源码文件(以.java后缀结尾)编译为Java字节码文件(以.class后缀结尾);
  • jar:用于把一组.class文件打包成一个.jar文件,便于发布;
  • javadoc:用于从Java源码中自动提取注释并生成文档;
  • jdb:Java调试器,用于开发阶段的运行调试。

1.8 第一个Java程序

我们来编写第一个Java程序。

打开文本编辑器,输入以下代码:

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

在一个Java程序中,你总能找到一个类似的定义,这个定义被称为class(类),这里的类名是Hello,大小写敏感,class用来定义一个类,public表示这个类是公开的,publicclass都是Java的关键字,必须小写,Hello是类的名字,按照习惯,首字母H要大写。而花括号{}中间则是类的定义。

public class Hello {
    ...
}

注意到类的定义中,我们定义了一个名为main的方法:

    public static void main(String[] args) {
        ...
    }

方法是可执行的代码块,一个方法除了方法名main,还有用()括起来的方法参数,这里的main方法有一个参数,参数类型是String[],参数名是argspublicstatic用来修饰方法,这里表示它是一个公开的静态方法,void是方法的返回类型,而花括号{}中间的就是方法的代码。

方法的代码每一行用;结束,这里只有一行代码,就是:

        System.out.println("Hello, world!");

它用来打印一个字符串到屏幕上。

Java规定,某个类定义的public static void main(String[] args)是Java程序的固定入口方法,因此,Java程序总是从main方法开始执行。

注意到Java源码的缩进不是必须的,但是用缩进后,格式好看,很容易看出代码块的开始和结束,缩进一般是4个空格或者一个tab。

最后,当我们把代码保存为文件时,文件名必须是Hello.java,而且文件名也要注意大小写,因为要和我们定义的类名Hello完全保持一致。

1.9 如何运行Java程序

Java源码本质上是一个文本文件,我们需要先用javacHello.java编译成字节码文件Hello.class,然后,用java命令执行这个字节码文件:

┌──────────────────┐
│    Hello.java    │<─── source code
└──────────────────┘
          │ compile
          ▼
┌──────────────────┐
│   Hello.class    │<─── byte code
└──────────────────┘
          │ execute
          ▼
┌──────────────────┐
│    Run on JVM    │
└──────────────────┘

因此,可执行文件javac是编译器,而可执行文件java就是虚拟机。

第一步,在保存Hello.java的目录下执行命令javac Hello.java

$ javac Hello.java

如果源代码无误,上述命令不会有任何输出,而当前目录下会产生一个Hello.class文件:

$ dir
Hello.class Hello.java

第二步,执行Hello.class,使用命令java Hello

$ java Hello
Hello, world!

小结:

一个Java源码只能定义一个public类型的class,并且class名称和文件名要完全一致;

使用javac可以将.java源码编译成.class字节码;

使用java可以运行一个已编译的Java程序,参数是类名。

1.10 使用Eclipse开发

1.10.1 安装Eclipse

Eclipse的发行版提供了预打包的开发环境。官方下载地址

我们需要下载的版本是Eclipse IDE for Java Developers:

image-20211130094710917

镜像下载:

大连东软下载地址

1.10.2 使用Eclipse

选择一个使用的workspace文件夹,保持默认也可。

image-20211130143656303

选择Review IDE configuration setting

image-20211130143813651

1-6都打对勾

image-20211130143931732

image-20211130144014575

1.10.3 新建Java项目

在Eclipse菜单选择“File”-“New”-“Java Project”,填入HelloWorld

如图勾选:

image-20211130144616932

image-20211130144724449

点击“Finish”就成功创建了一个名为HelloWorld的Java工程。

image-20211130144816791

展开HelloWorld工程,选中源码目录src,点击右键,在弹出菜单中选择“New”-“Class”:

image-20211130150205204

image-20211130150320812

点击”Finish“,就自动在src目录下创建了一个名为Hello.java的源文件。我们双击打开这个源文件,填上代码:

image-20211130151424652

保存,然后选中文件Hello.java,点击右键,在弹出的菜单中选中Run As Java Application

image-20211130151506466

Console窗口中就可以看到运行结果:

image-20211130151624520


2. Java基础

2.1 变量与常量

2.1.1 标识符

单个字母我们叫它字符,一串字母就叫标识符,例如我们定义的class名字是HelloHello就是一个标识符。用双引号引起来的一串字母叫做字符串。

public class Hello
  • 标识符可以由字母、数字、下划线(_)和美元符($)组成,不能以数字开头
  • 标识符严格区分大小写
  • 标识符不能是Java关键字和保留字
  • 标识符的命名最好能反映出其作用
2.1.2 关键字

Java关键字是对Java编译器有特殊含义的字符串,是编译器和程序员的一个约定,程序员利用关键字来告诉编译器其声明的变量类型、类、方法特性等信息。Java语言共定义了如下所示的关键字。

关键字 含义
abstract 表明类或者成员方法具有抽象属性
assert 断言,用来进行程序调试
boolean 基本数据类型之一,声明布尔类型的关键字
break 提前跳出一个块
byte 基本数据类型之一,字节类型
case 用在switch语句之中,表示其中的一个分支
catch 用在异常处理中,用来捕捉异常
char 基本数据类型之一,字符类型
class 声明一个类
const 保留关键字,没有具体含义
continue 回到一个块的开始处
default 默认,例如,用在switch语句中,表明一个默认的分支。Java8 中也作用于声明接口函数的默认实现
do 用在do-while循环结构中
double 基本数据类型之一,双精度浮点数类型
else 用在条件语句中,表明当条件不成立时的分支
enum 枚举
extends 表明一个类型是另一个类型的子类型。对于类,可以是另一个类或者抽象类;对于接口,可以是另一个接口
final 用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变,用来定义常量
finally 用于处理异常情况,用来声明一个基本肯定会被执行到的语句块
float 基本数据类型之一,单精度浮点数类型
for 一种循环结构的引导词
goto 保留关键字,没有具体含义
if 条件语句的引导词
implements 表明一个类实现了给定的接口
import 表明要访问指定的类或包
instanceof 用来测试一个对象是否是指定类型的实例对象
int 基本数据类型之一,整数类型
interface 接口
long 基本数据类型之一,长整数类型
native 用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的
new 用来创建新实例对象
package
private 一种访问控制方式:私用模式
protected 一种访问控制方式:保护模式
public 一种访问控制方式:共用模式
return 从成员方法中返回数据
short 基本数据类型之一,短整数类型
static 表明具有静态属性
strictfp 用来声明FP_strict(单精度或双精度浮点数)表达式遵循IEEE 754算术规范
super 表明当前对象的父类型的引用或者父类型的构造方法
switch 分支语句结构的引导词
synchronized 表明一段代码需要同步执行
this 指向当前实例对象的引用
throw 抛出一个异常
throws 声明在当前定义的成员方法中所有需要抛出的异常
transient 声明不用序列化的成员域
try 尝试一个可能抛出异常的程序块
void 声明当前成员方法没有返回值
volatile 表明两个或者多个变量必须同步地发生变化
while 用在循环结构中
2.1.3 变量

变量的概念:变量就是初中数学的代数的概念,例如一个简单的方程,x,y都是变量

  • 内存中的一个存储区域
  • 该区域有自己的名称(变量名)和类型(数据类型)和值
  • Java中每个变量必须先声明,再赋值,然后才能使用
  • 该区域的数据可以在同一类型范围内不断变化
  • Java 中的变量有四个基本属性:变量名,数据类型,存储单元和变量值

变量名的命名规则

  • 满足标识符命名规则
  • 符合驼峰法命名规范
  • 尽量简单,做到见名知意
  • 变量名的长度没有限

变量定义示例

内容 变量
年龄 age
学生姓名 stuName

扩展:类的命名规则

  • 满足Pascal命名法规范(单词的首字母都要大写)
示例
类名 HelloWorld
2.1.4 数据类型

image-20211201113509473

2.1.5 整型
  • Java中有三种表示整数的方法:十进制、八进制、十六进制 例:123,023,0x1357,0X3c,0x1abcL

进制表示

  • 八进制:以0开头,包括0-7的数字 例:037,056

  • 十六进制表示:以0x或0X开头,包括0-9的数字,及字母a-f,A-F 例:0x12,0xabcf,0XABCFF

变量声明

  • 格式:数据类型 变量名; 例:
  • int n声明整型变量n
  • long count 声明长整型变量count

赋值

  • 使用“=”运算符进行赋值

  • “=”叫作赋值运算符,将运算符右边的值赋给左边的变量。

例:int n;定义int型变量n n=3;3赋值给n

  • 可以在定义变量的同时给变量赋值,即变量的初始化。 例:int n=3; 数据类型 变量名=变量值
变量定义例
int octal=037; //定义int类型变量存放八进制数据
long longNumber=0xa2cdf3ffL; //定义变量存放十六进制长整型数据
short shortNumber=123; //定义变量存放短整型数据
byte b=10; //定义变量存放byte类型数据

注意:

  • 整型常量默认情况下是int类型,如果表示长整型则在末尾加lL
  • 语句以分号结束
2.1.6 浮点型
  • 浮点型常量默认情况下表示double类型,也可以在值后加d或D 如:123.43d或123.43D
  • 表示float类型,则需要在常量后加f或F 如:23.4f或23.4F
2.1.7 字符型
  • 字符型常量用单引号内的单个字符表示

如:‘a’‘b’‘$’

  • 如何定义字符型变量?

char a=‘a’;

char ch=65;

  • 疑问:怎么整型还能赋值给char类型?
2.1.8 布尔类型
  • 布尔值只能定义为true和false

例:boolean b=true;

2.1.9 字符串
  • 双引号引起来的0个或多个字符

例:string "Hello World"

2.1.10 常量
  • 不能被修改的值,一般用大写字母表示

final int PI=3.1415926

2.1.11 基本数据类型变量的存储
  • 数据类型非为基本数据类型和引用数据类型
  • 引用数据类型包括数组和类等
  • 类定义的变量又叫对象

存储的位置的区别

  • 寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.

  • 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)

  • 堆:存放所有new出来的对象。

  • 静态域:存放静态成员(static定义的)

  • 常量池:存放字符串常量和基本类型常量(public static final)。

  • 非RAM存储:硬盘等永久存储空间

这里我们主要关心栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。

对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。

image-20211201133018624

image-20211201133648727

对于以上这段代码,date为局部变量,i,d,m,y都是形参为局部变量,daymonthyear为成员变量。下面分析一下代码执行时候的变化:

  • main方法开始执行:int date = 9; date局部变量,基础类型(没有引用一说,只有值),值存在栈中。

  • Test test = new Test(); test为对象引用,存在栈中,对象(new Test())存在堆中。

  • test.change(date); i为局部变量,值存在栈中。当方法change执行完成后,i就会从栈中消失。

  • BirthDate d1= new BirthDate(7,7,1970); d1 为对象引用,存在栈中,对象(new BirthDate())存在堆中,其中dmy为局部变量存储在栈中,且它们的类型为基础类型,因此它们的数据也存储在栈中。 day,month,year为成员变量,它们存储在堆中(new BirthDate())。当BirthDate构造方法执行完之后,d,m,y将从栈中消失。

  • main方法执行完之后,date变量,testd1引用将从栈中消失,new Test(),new BirthDate()将等待垃圾回收

2.1.12 ASCII码、Unicode编码和转义字符

ASCII(American Standard Code for Information Interchange,美国标准信息交换代码)

  • 基于拉丁字母的一套电脑编码系统
  • 主要用于显示现代英语和其他西欧语言

ASCII码表示

  • 使用7位或8位二进制数组合来表示128或256种可能的字符。

  • 标准ASCII码使用7位二进制来表示所有的大写字母和小写字母, 数字0-9,标点符号,以及在美式英语种使用的控制字符。

  • 后128个称为扩展ASCII码,用于表示特殊符号、外来语字母和 图形符号。

Unicode编码

Unicode编码又称为统一码、万国码,Unicode编码的目标是支持世界上所以的字符集

  • char c=‘\u005d’;

  • Unicode表示法,在值前加前缀\u

ASCII 编码一览表(淡黄色背景为控制字符,白色背景为可显示字符

二进制 十进制 十六进制 字符/缩写 解释
00000000 0 00 NUL (NULL) 空字符
00000001 1 01 SOH (Start Of Headling) 标题开始
00000010 2 02 STX (Start Of Text) 正文开始
00000011 3 03 ETX (End Of Text) 正文结束
00000100 4 04 EOT (End Of Transmission) 传输结束
00000101 5 05 ENQ (Enquiry) 请求
00000110 6 06 ACK (Acknowledge) 回应/响应/收到通知
00000111 7 07 BEL (Bell) 响铃
00001000 8 08 BS (Backspace) 退格
00001001 9 09 HT (Horizontal Tab) 水平制表符
00001010 10 0A LF/NL(Line Feed/New Line) 换行键
00001011 11 0B VT (Vertical Tab) 垂直制表符
00001100 12 0C FF/NP (Form Feed/New Page) 换页键
00001101 13 0D CR (Carriage Return) 回车键
00001110 14 0E SO (Shift Out) 不用切换
00001111 15 0F SI (Shift In) 启用切换
00010000 16 10 DLE (Data Link Escape) 数据链路转义
00010001 17 11 DC1/XON (Device Control 1/Transmission On) 设备控制1/传输开始
00010010 18 12 DC2 (Device Control 2) 设备控制2
00010011 19 13 DC3/XOFF (Device Control 3/Transmission Off) 设备控制3/传输中断
00010100 20 14 DC4 (Device Control 4) 设备控制4
00010101 21 15 NAK (Negative Acknowledge) 无响应/非正常响应/拒绝接收
00010110 22 16 SYN (Synchronous Idle) 同步空闲
00010111 23 17 ETB (End of Transmission Block) 传输块结束/块传输终止
00011000 24 18 CAN (Cancel) 取消
00011001 25 19 EM (End of Medium) 已到介质末端/介质存储已满/介质中断
00011010 26 1A SUB (Substitute) 替补/替换
00011011 27 1B ESC (Escape) 逃离/取消
00011100 28 1C FS (File Separator) 文件分割符
00011101 29 1D GS (Group Separator) 组分隔符/分组符
00011110 30 1E RS (Record Separator) 记录分离符
00011111 31 1F US (Unit Separator) 单元分隔符
00100000 32 20 (Space) 空格
00100001 33 21 !
00100010 34 22 "
00100011 35 23 #
00100100 36 24 $
00100101 37 25 %
00100110 38 26 &
00100111 39 27 '
00101000 40 28 (
00101001 41 29 )
00101010 42 2A *
00101011 43 2B +
00101100 44 2C ,
00101101 45 2D -
00101110 46 2E .
00101111 47 2F /
00110000 48 30 0
00110001 49 31 1
00110010 50 32 2
00110011 51 33 3
00110100 52 34 4
00110101 53 35 5
00110110 54 36 6
00110111 55 37 7
00111000 56 38 8
00111001 57 39 9
00111010 58 3A :
00111011 59 3B ;
00111100 60 3C <
00111101 61 3D =
00111110 62 3E >
00111111 63 3F ?
01000000 64 40 @
01000001 65 41 A
01000010 66 42 B
01000011 67 43 C
01000100 68 44 D
01000101 69 45 E
01000110 70 46 F
01000111 71 47 G
01001000 72 48 H
01001001 73 49 I
01001010 74 4A J
01001011 75 4B K
01001100 76 4C L
01001101 77 4D M
01001110 78 4E N
01001111 79 4F O
01010000 80 50 P
01010001 81 51 Q
01010010 82 52 R
01010011 83 53 S
01010100 84 54 T
01010101 85 55 U
01010110 86 56 V
01010111 87 57 W
01011000 88 58 X
01011001 89 59 Y
01011010 90 5A Z
01011011 91 5B [
01011100 92 5C \
01011101 93 5D ]
01011110 94 5E ^
01011111 95 5F _
01100000 96 60 `
01100001 97 61 a
01100010 98 62 b
01100011 99 63 c
01100100 100 64 d
01100101 101 65 e
01100110 102 66 f
01100111 103 67 g
01101000 104 68 h
01101001 105 69 i
01101010 106 6A j
01101011 107 6B k
01101100 108 6C l
01101101 109 6D m
01101110 110 6E n
01101111 111 6F o
01110000 112 70 p
01110001 113 71 q
01110010 114 72 r
01110011 115 73 s
01110100 116 74 t
01110101 117 75 u
01110110 118 76 v
01110111 119 77 w
01111000 120 78 x
01111001 121 79 y
01111010 122 7A z
01111011 123 7B {
01111100 124 7C |
01111101 125 7D }
01111110 126 7E ~
01111111 127 7F DEL (Delete) 删除
转义字符 意义 ASCII码值(十进制)
\a 响铃(BEL) 007
\b 退格(BS) ,将当前位置移到前一列 008
\f 换页(FF),将当前位置移到下页开头 012
\n 换行(LF) ,将当前位置移到下一行开头 010
\r 回车(CR) ,将当前位置移到本行开头 013
\t 水平制表(HT) (跳到下一个TAB位置) 009
\v 垂直制表(VT) 011
\ 代表一个反斜线字符''\' 092
\' 代表一个单引号(撇号)字符 039
\" 代表一个双引号字符 034
\? 代表一个问号 063
\0 空字符(NUL) 000
\ddd 1到3位八进制数所代表的任意字符 三位八进制
\xhh 十六进制所代表的任意字符 十六进制
2.1.13 小节练习

接下来我们在eclipse中试验。

首先设置下字体,Preferences--General--Appearance--colors and Fonts

image-20211201130050661

实验以下代码

package net.kokwind;

public class VarDemo {

    public static void main(String[] args) {
        // 定义一个整形变量
        int a=1;
        System.out.println("a=" + a);
        // 定义一个单精度浮点型变量
        float b=1234.567f;
        System.out.println("b=" + b);
        // 定义一个双精度浮点型变量
        double c=11234.567d;
        System.out.println("c=" + c);
        // 将整形赋值给浮点型,会添加小数点
        double d=123;
        System.out.println("d=" + d);
        // 将变量c的值复制给e,都是双精度浮点型变量
        double e=c;
        System.out.println("e=" + e);
        // 将变量b的值复制给f,b是单精度浮点型变量
        double f=b;
        System.out.println("f=" + f);
        //定义一个变量存放字符
        char g='a';
        System.out.println("g=" + g);
        //定义h=65时,会默认转换成ascii码变成A
        char h=65;
        System.out.println("h=" + h);
        //定义i超出65535时,需要强制类型转换
        char i=(char)65536;
        System.out.println("i=" + i);
        //定义bianliang cunfang unicode编码表示的字符
        char j='\u005d';
        System.out.println("j=" + j);
        //定义一个字符串
        String k="Hello";
        System.out.println("k=" + k);
        //定义三个整形变量,n等于l+m
        int l=1,m=2,n;
        n = l + m;
        System.out.println("n=" + n);
        //数据类型转换例,从结果上看,如果做强制类型转换,精度会缺失
        double o=1001234567890111L;
        System.out.println("o=" + o);
        float p=(float)o;
        System.out.println("p=" + p);
    }

}

输出结果

a=1
b=1234.567
c=11234.567
d=123.0
e=11234.567
f=1234.5670166015625
g=a
h=A
i=口
j=]
k=Hello
n=3
o=1.001234567890111E15
p=1.00123459E15

image-20211201152926801

2.2 运算符

2.2.1 表达式
  • 表达式由运算符和操作数组成

如: sum=num1+num2

2.2.2 运算符概述
  • 算术运算符
  • 赋值运算符
  • 关系运算符
  • 逻辑运算符
  • 条件运算符
  • 位运算符
2.2.3 算术运算符
  • 算术运算符主要用于进行基本的算术运算,如加法、减法、乘法和除法等
算数运算符 名称 举例
+ 加法 5+10=15
- 减法 20-10=10
* 乘法 3*9=27
/ 除法 40/5=8
% 求余数 17/5=2
++ 自增1 int i=1;i++
-- 自减1 int i=10;--1

代码示例

package net.kokwind;

public class MathDemo {
    public static void main(String[] args) {
        int x=10, y=5;
        int z;
        //加法
        z=x+y;
        System.out.println("加法z=" + z);
        //减法
        z=x-y;
        System.out.println("减法z=" + z);
        //乘法
        z=x*y;
        System.out.println("乘法z=" + z);
        //除法
        z=x/y;
        System.out.println("除法z=" + z);
        //求余数
        x=16;
        z=x%y;
        System.out.println("求余数z=" + z);
        //自增1 
        //++出现在左边,先执行自增,然后将值赋给变量z
        //++出现在右边,先将值赋给变量z,然后执行自增
        z=y++;
        System.out.println("自增z=" + z);
        System.out.println("自增y=" + y);
        //自减1
        x=--x;
        System.out.println("自减x=" + x);
        //字符串拼接,在前面加两个双引号
        x=10;
        y=5;
        System.out.println("字符串拼接"+x + y);
    }
}

输出

加法z=15
减法z=5
乘法z=50
除法z=2
求余数z=1
自增z=5
自增y=6
自减x=15
字符串拼接105
2.2.4 赋值运算符
  • 格式:变量=表达式;

例:int n=3;//将3赋值给变量n

注意:赋值运算符是从右往左运算!

复合赋值运算符

运算符 表达式 计算 结果(假设x=15)
+= x+=5 x=x+5 20
-= x-=5 x=x-5 10
*= x*=5 x=x*5 75
/= x/=5 x=x/5 3
%= x%=5 x=x%5 0
2.2.5 关系运算符
  • 比较运算符用于判断两个数据的大小,如大于
  • 比较的结果是一个布尔值
运算符 名称 表达式 结果
> 大于 5>2 true
< 小于 6<3 false
>= 大于等于 5>=1 true
<= 小于等于 6<=2 false
== 等于 5==1 false
!= 不等于 5!=2 true
2.2.6 逻辑运算符
  • 比较运算符用于判断两个数据的大小,如大于
  • 比较的结果是一个布尔值
运算符 名称 表达式
&&或& x1&&x2
||或| x1||x2
! !x1
  • 问题:升学考试,英语、数学、C语言三门总成绩大于等于230, 并且英语成绩大于等于60,才能升学。
  • 三门总成绩大于等于230,表示为:sum>=230

  • 英语成绩大于等于60,表示为en>=60

  • 逻辑“与”运算符

sum sum>=230 en en>=60 结果
260 true 65 true true
260 true 50 false false
210 false 65 true false
210 false 55 false false
  • Java中&&&的区别 Java中&&&都是表示与的逻辑运算符,都表示逻辑运输符and,当两边的表达式都为true的时候,整个运算结果才为true,否则为false

&&的短路功能,当第一个表达式的值为false的时候,则不再计算第二个表达式;&则两个表达式都执行。

  • 扩展:

    Java中=是赋值运算,

    ==判断值是否相等,

    ===是判断的是值及类型是否完全相等,而===只在JavaScript中有

  • 比如:

    a=b 就是把b的值赋予给a; a==b 就是判断a等于b

  • &&&的区别示例

public class Condemo {
     public static void main(String[] args) {
          int n=3;
          boolean b=(3>5)&&((n++)<2);
          System.out.println("短路运算符b="+b);
          System.out.println("短路运算符n="+n);
          b=(3>5)&((n++)<2);
          System.out.println("b="+b);
          System.out.println("n="+n);

输出

短路运算符b=false
短路运算符n=3
b=false
n=4
  • 逻辑“或”运算符
  • 问题:还是升学考试,英语、数学、C语言三门总成绩大于等于230, 或者英语成绩大于等于85,也能升学。
  • 三门总成绩大于等于230,表示为:sum>=230

  • 英语成绩大于等于85,表示为en>=85

sum sum>=230 en en>=85 结果
260 true 85 true true
260 true 50 false true
210 false 95 true true
210 false 55 false false
  • |||的区别参考&&&

  • 逻辑"非"运算符

  • !运算符

  • 对原条件进行取反

  • 例:输入一个数,判断是否能被3整除,并输出相应的提示信息。

import java.util.Scanner;

public class Condemo {

    public static void main(String[] args) {
        //输入一个整数
        System.out.println("请输入一个整数:");
        Scanner sc=new Scanner(System.in);  //Scaner里面的System.in可以从键盘输入
        int n=sc.nextInt();
        if(!(n%3==0)) {
            System.out.println(n+"不能被3整除");
        }
        else {
            System.out.println(n+"能被3整除");
        }
    }
}
  • 输出:
请输入一个整数:
21
21能被3整除
2.2.7 条件运算符
  • Java中的条件运算符是三目运算符

  • 语法结构:

布尔表达式?表达式1:表达式2

  • 当布尔表达式的值为true,则返回表达式1的值,否则返回表达式2的值

  • 示例:求两个数的最大值并输出

  package net.kokwind;

  public class Condemo {

    public static void main(String[] args) {
          //使用if判断大小
          int a=10,b=7,max;
          if(a>b) {
            max=a;
          }else {
            max=b;
          }
          System.out.println("使用if判断max="+max);
          //使用条件运算符判断大小
          max=a>b?a:b;
          System.out.println("使用运算符判断max="+max);
    }
  }

输出:

使用if判断max=10
使用运算符判断max=10
2.2.8 运算符的优先级
  • 执行顺序
优先级 运算符 结合性
1 ()、[]、{} 从左向右
2 !、+、-、~、++、-- 从右向左
3 *、/、% 从左向右
4 +、- 从左向右
5 «、»、>>> 从左向右
6 <、<=、>、>=、instanceof 从左向右
7 ==、!= 从左向右
8 & 从左向右
9 ^ 从左向右
10 | 从左向右
11 && 从左向右
12 || 从左向右
13 ?: 从右向左
14 =、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>= 从右向左
2.2.9 综合案例
  • if-else语句判断输入的年份是否为闰年。

  • 闰年的判断规则:能被4整除但不能被100整除的年份,或者能被400整除的年份

  package net.kokwind;

  import java.util.Scanner;

  public class Condemo {

    public static void main(String[] args) {
          System.out.println("请输入年份:");
          Scanner sc=new Scanner(System.in);
          int year=sc.nextInt();
          //闰年的判断规则:能被4整除但不能被100整除或被400整除
          if(((year%4==0)&(year%100!=0))|(year%400==0)) {
            System.out.println(year+"是闰年");
          }else {
            System.out.println(year+"不是闰年");
          }
    }
  }

输出:

  请输入年份:
  2020
  2020是闰年

2.3 流程控制

2.3.1 if条件控制

如果要根据条件来决定是否执行某一段代码,就需要if语句。

  • 简单if语句的格式
  if(条件)
  {
      <语句块>
  }
  • if-else语句的格式
  if(条件)
  {
      <语句块>  //条件满足时
  }
  else
  {
      <语句块>  //条件不满足时    
  }

例:用程序来判断是否及格。

  package net.kokwind;

  public class Condemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
          int n = 75;
          if (n >= 60) {
              System.out.println("及格");
          } else {
              System.out.println("不及格");
          }
    }

  }

输出

  及格
2.3.2 switch多重选择条件

swith是根据某个表达式的结果,分别去执行不同的分支

  • 语法格式
  switch (option) {
  case 3:
      ...
      break;
  case 2:
      ...
      break;
  case 1:
      ...
      break;
  }
  package net.kokwind;

  public class Condemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
          int option = 1;
          switch (option) {
          case 1:
              System.out.println("Selected 1");
              break;
          case 2:
              System.out.println("Selected 2");
              break;
          case 3:
              System.out.println("Selected 3");
              break;
          default:
              System.out.println("Not selected");
              break;
          }
    }
  }

输出:

  Selected 1

小节:

  • if结构:

    • 判断条件是布尔类型

    • 判断条件是一个范围

  • switch结构:

    • 判断条件是常量值

    • 当条件都不满足时,就执行default语句后面内容

    • 如果不写break语句,会在满足条件的语句执行完后,继续执行后续的语句。

2.3.3 while循环结构

循环语句是根据条件做循环计算,在条件满足时继续循环,条件不满足时退出循环。

  • 语法格式
  while (条件表达式) {
      循环语句
  }
  // 继续执行后续代码
  • while循环在每次循环开始前,首先判断条件是否成立。

如果计算结果为true,就把循环体内的语句执行一遍,如果计算结果为false,那就直接跳到while循环的末尾,继续往下执行。

我们用while循环10次,可以这么写:

  package net.kokwind;

  public class Condemo {

    public static void main(String[] args) {
          int n = 1;
          while (n <= 10) { // 循环条件是n <= 10
              System.out.println("循环里的n=" + n); 
              n ++; // n自身加1
          }
          System.out.println("最后n=" + n); // 101           break;
    }
  }

输出:

  循环里的n=1
  循环里的n=2
  循环里的n=3
  循环里的n=4
  循环里的n=5
  循环里的n=6
  循环里的n=7
  循环里的n=8
  循环里的n=9
  循环里的n=10
  最后n=11

注意到while循环是先判断循环条件,再循环,因此,有可能一次循环都不做。

2.3.4 do-while循环结构

do while循环则是先执行循环,再判断条件,条件满足时继续循环,条件不满足时退出。它的用法是:

  • 语法格式
  do {
      执行循环语句
  } while (条件表达式);
  • do while循环会至少循环一次。

我们把对1到10的循环用do while循环改写一下:当设置n等于11时

  package net.kokwind;

  public class Condemo {

    public static void main(String[] args) {
          int n = 11;
          do { // 循环条件是n <= 10
              System.out.println("循环里的n=" + n); 
              n ++; // n自身加1
          } while (n <= 10) ;
          System.out.println("最后n=" + n); // 11           break;
    }
  }

输出:

  循环里的n=11
  最后n=12 

注意:

do while循环先执行循环,再判断条件;

do while循环会至少执行一次。

2.3.5 for循环结构

for循环的功能非常强大,它使用计数器实现循环。for循环会先初始化计数器,然后,在每次循环前检测循环条件,在每次循环后更新计数器。计数器变量通常命名为i。

  • 语法格式
  for (初始条件; 循环检测条件; 循环后更新计数器) {
      // 执行语句
  }
  • 我们把对1到10的循环用for循环改写一下:
  package net.kokwind;

  public class Condemo {

    public static void main(String[] args) {
          for (int i=1; i<=10; i++) {
            System.out.println("循环里的i="+i);
          }
    }
  }

输出:

  循环里的i=1
  循环里的i=2
  循环里的i=3
  循环里的i=4
  循环里的i=5
  循环里的i=6
  循环里的i=7
  循环里的i=8
  循环里的i=9
  循环里的i=10
  • for each循环

for循环经常用来遍历数组,因为通过计数器可以根据索引来访问数组的每个元素:

  package net.kokwind;

  public class Condemo {

    public static void main(String[] args) {
        int[] ns = { 1, 4, 9, 16, 25 };
        for (int i=0; i<ns.length; i++) {
            System.out.println(ns[i]);
        }
    }
  }

但是,很多时候,我们实际上真正想要访问的是数组每个元素的值。Java还提供了另一种for each循环,它可以更简单地遍历数组:

  package net.kokwind;

  public class Condemo {

    public static void main(String[] args) {
          int[] ns = { 1, 4, 9, 16, 25 };
          for (int n : ns) {
              System.out.println(n);
          }
    }
  }

输出:

  1
  4
  9
  16
  25

小结:

for循环通过计数器可以实现复杂循环;

for each循环可以直接遍历数组的每个元素;

2.3.6 break和continue

在循环过程中,可以使用break语句跳出当前循环。我们来看一个例子:

  • break
  package net.kokwind;

  public class Condemo {

    public static void main(String[] args) {
          for (int i=1; i<=10; i++) {
            if (i==5) {
                break;
            }
            System.out.println("循环里的i="+i);
          }
    }
  }

输出:

  循环里的i=1
  循环里的i=2
  循环里的i=3
  循环里的i=4

break会跳出当前循环,也就是整个循环都不会执行了。而continue则是提前结束本次循环,直接继续执行下次循环。我们看一个例子:

  • continue
  package net.kokwind;

  public class Condemo {

    public static void main(String[] args) {
          for (int i=1; i<=10; i++) {
            if (i==5) {
                continue;
            }
            System.out.println("循环里的i="+i);
          }
    }
  }

输出:

  循环里的i=1
  循环里的i=2
  循环里的i=3
  循环里的i=4
  循环里的i=6
  循环里的i=7
  循环里的i=8
  循环里的i=9
  循环里的i=10

小结:

break语句可以跳出当前循环;

break语句通常配合if,在满足条件时提前结束整个循环;

break语句总是跳出最近的一层循环;

continue语句可以提前结束本次循环;

continue语句通常配合if,在满足条件时提前结束本次循环。

2.4 数组

数组是相同类型的数据按顺序组成的一种引用数据类型

2.4.1 一维数组
  • 语法格式:
格式一:
  数据类型[] 数组名;
  int[] myIntArray;

格式二:
  数据类型 数组名[];
  int myIntArray[];
  • 数组创建:数组长度必须指定
格式一:先声明后创建
  数据类型[] 数组名;
  数组名 = new 数据类型[数组长度];
  int[] arr;
  arr=new int[10];//创建一个长度为10的整型数组
格式二:声明的同时创建数组
  数据类型 数组名[] = new 数据类型[数组长度];
  int[] arr=new int[10];//创建一个长度为10的整型数组
  • 数组初始化:声明数组的同时给数组赋值,叫做数组的初始化
 int[] arr={1,2,3,4,5,6,7,8,9,10};
 数组的长度就是初始化时给的数据的个数
  • 数组元素的引用:
 语法格式:
   数组名[下标];
   注意:下标从0开始
 int[] arr={1,2,3,4,5,6,7,8,9,10};
 arr[0],arr[1],……,arr[8],arr[9]
  • 数组长度
 int[] arr={1,2,3,4,5,6,7,8,9,10};
 属性length表示数组的长度,如arr.length 
  • 数组应用:增强型for循环
package net.kokwind;

public class ArrDemo {

    public static void main(String[] args) {
         int[] arr={1,2,3,4,5,6,7,8,9,10};
         //普通for循环打印数组的值
         for(int i=0;i<arr.length;i++) {
             System.out.println(arr[i]);
         }
         // 增强型for循环打印数组的值
         for(int n:arr){
            System.out.println(n);
         }
    }
}

输出:

1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
  • 典型应用:冒泡排序
  • 对一组整数按照由小到大的顺序进行排序
package net.kokwind;

public class ArrDemo {

    public static void main(String[] args) {
         int[] arr={34,53,12,32,56,17,89,24,78};
         //排序前打印数组的值
         System.out.print("冒泡排序前的值: ");
         for(int n:arr){
             System.out.print(n+" ");
         }
         System.out.println();
         int temp=0;
         /*冒泡排序
          * 它重复地走访过要排序的元素列,
          * 依次比较两个相邻的元素,
          * 如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。
          * 走访元素的工作是重复地进行直到没有相邻元素需要交换,
          * 也就是说该元素列已经排序完成。
         */
         for(int k=0;k<arr.length-1;k++) {
            //内重循环控制每次排序
             for(int i=0;i<arr.length-k-1;i++) {
                 if(arr[i]>arr[i+1]) {
                     temp=arr[i];
                     arr[i]=arr[i+1];
                     arr[i+1]=temp;
                 }
             }
         }
         // 增强型for循环打印数组的值
         System.out.print("冒泡排序后的值: ");
         for(int n:arr){
             System.out.print(n+" ");
         }
    }
}

输出:

冒泡排序前的值: 34 53 12 32 56 17 89 24 78 
冒泡排序后的值: 12 17 24 32 34 53 56 78 89 
2.4.2 二维数组
  • 数组的声明和创建:
格式一:
  数据类型[][] 数组名;
  int[][] myIntArray;

格式二:
  数据类型 数组名[][];
  int myIntArray[][];

格式三:
  数据类型[] 数组名[];
  int[] myIntArray[];
  • 示例:
package net.kokwind;

import java.util.Arrays;

public class ArrDemo {

    public static void main(String[] args) {
         System.out.print("二位数组开始 ");
         int[][] num1= {{78,98},{65,31,42},{98}};
         System.out.println("num1数组的第一行的列数为: "+num1[0].length);
         // 常规for循环打印二维数组的值
         for(int i=0;i<num1.length;i++) {
             for(int j=0;j<num1[i].length;j++) {
                 System.out.print(num1[i][j]+ " ");
             }
             System.out.println();
         }
         // 增强型for循环打印二维数组的值
         for (int[] arr1:num1) {
                for (int n : arr1) {
                    System.out.print(n);
                    System.out.print(", ");
                }
                System.out.println();
            }
         //或者使用Java标准库的Arrays.deepToString():
         System.out.println(Arrays.deepToString(num1));
    }
}

输出:

二位数组开始 num1数组的第一行的列数为: 2
78 98 
65 31 42 
98 
78, 98, 
65, 31, 42, 
98, 
[[78, 98], [65, 31, 42], [98]]

2.5 方法

所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块

2.5.1 方法的声明和调用
  • 语法格式:
语法格式:
访问修饰符 返回类型 方法名(参数列表){
   方法体
}
  • 根据方法是否带参数、是否返回值,可分为四类: -无参无返回值方法 -无参带返回值方法 -带参无返回值方法 -带参带返回值方法
2.5.2 无参无返回值方法
  • 例:一行打印一串星号
package net.kokwind;

public class MethodDemo {
    //打印输出星号的方法
    public void printStar() {
        System.out.println("****************************");
    }

    public static void main(String[] args) {
        //创建一个MethodDemo类的对象md
        MethodDemo md=new MethodDemo();
        //使用对象名.方法名()去调用方法 
        md.printStar();
        System.out.println("欢迎来到java世界!!!");
        md.printStar();
    }
}

输出:

****************************
欢迎来到java世界!!!
****************************
2.5.3 无参带返回值方法
  • 例:求长方形的面积
package net.kokwind;

public class MethodDemo {
    //求长方形面积的方法
    public int area() {
        int length=10;
        int width=3;
        int area=length*width;
        return area;
    }

    public static void main(String[] args) {
        MethodDemo md=new MethodDemo();
        System.out.println("长方形的面积为:"+md.area());
    }
}

输出:

长方形的面积为:30
2.5.4 带参无返回值方法
  • 例:定义一个方法,打印输出最大值
package net.kokwind;

public class MethodDemo {
    //求最大值的方法
    public void max(int a,int b) {
        int max;
        if(a>b) {
            max=a;
        }else {
            max=b;
        }
        System.out.println("两个数的最大值是:"+max);
    }

    public static void main(String[] args) {
        MethodDemo md=new MethodDemo();
        md.max(3, 2);
    }
}

输出:

最大值是:3
2.5.5 带参无返回值方法
  • 例:定义一个求n!的方法,然后再求1!+2!+3!+4!+5!
package net.kokwind;

public class MethodDemo {
    //求阶乘的方法
    public int fac(int n) {
        int fac=1;
        for(int i=1;i<=n;i++) {
            fac*=i;
        }
        return fac;
    }

    public static void main(String[] args) {
        MethodDemo md=new MethodDemo();
        //求3的阶乘
        int fac=md.fac(3);
        System.out.println("3的阶乘是"+fac);
        //求1!+2!+3!+4!+5!的阶乘
        int s=md.fac(1)+md.fac(2)+md.fac(3)+md.fac(4)+md.fac(5);
        System.out.println("1!+2!+3!+4!+5!的阶乘是"+s);
        //使用循环求1!+2!+3!+4!+5!的阶乘
        int sum=0;
        for(int i=1;i<=5;i++){
            sum+=md.fac(i);
        }
        System.out.println("1!+2!+3!+4!+5!的阶乘是"+sum);
    }
}

输出:

3的阶乘是6
1!+2!+3!+4!+5!的阶乘是153
1!+2!+3!+4!+5!的阶乘是153
2.5.6 数组作为方法参数
  • 例:定义方法,打印输出数组元素的值
package net.kokwind;

public class MethodDemo {
    //打印输出数组元素的值
    public void printArray(int[] arr) {
        for(int i:arr) {
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        //定义一个数组
        int[] arr= {3,2,1,33};
        MethodDemo md=new MethodDemo();
        md.printArray(arr);
    }
}

输出:

3
2
1
33
2.5.7 方法的重载
  • 方法的重载:方法名相同,参数列表不同

判断下列哪些方法是重载的方法 - public void hello(){}

  • public int hello(){}

  • public void hello(String s){}

  • public void hello(int n){}

  • public void hello(float f1,float f2){}

  • public void hello1(){}

  • 定义3个方法,实现int、double和数组类型和的问题

package net.kokwind;

public class MethodDemo {
    //方法的重载:方法名相同,参数列表不同
    //求两个int类型数的和
    public int plus(int a,int b) {
        return a+b;
    }
    //求两个double类型数的和
    public double plus(double a,double b) {
        return a+b;
    }
    //求整形数组元素的累加和
    public int plus(int[] arr) {
        int sum=0;
        for(int i:arr) {
            sum+=i;
        }
        return sum;
    }

    public static void main(String[] args) {
        //定义一个数组
        int[] arr= {1,2,3,4,5,6,7,8,9};
        MethodDemo md=new MethodDemo();
        //求整形数的和
        System.out.println(md.plus(2,3));
        //求double型数的和
        System.out.println(md.plus(2.2,4.2));
        //求数组的和
        System.out.println(md.plus(arr));

    }
}

输出:

5
6.4
45

2.6 对象

万物皆对象,显示存在的客观事物都可以成为对象

对象:用来描述客观事物的一个实体,由一组属性和方法构成

2.6.1 类和对象
  • 类是模子,确定对象将会拥有的特征(属性)和行为(方法) • 类的特点 • 类是对象的类型 • 具有相同属性和方法的一组对象的集合
  • 对象是真是存在的,能看得见摸得到的。对象是特定类型的数据
2.6.2 对象的属性和方法
  • 什么是对象的属性和方法 • 属性:对象具有的各种静态特征 • “有什么” • 方法:对象具有的各种动态行为 • “能做什么
2.6.3 类和对象的关系
  • 类是抽象的概念,仅仅是模板
  • 对象是一个你能够看得到、摸得着的具体实体
  • 类是对象的类型
  • 对象是特定类型的数据
  • 具体开发过程中,先定义类再实例化对象
2.6.4 类和对象的示例
  • 首先创建一个类
package net.kokwind.animal;
/**
 * 宠物猫类
 * @author Administrator
 *
 */
public class Cat {
    //属性:昵称、年龄、体重、品种
    String name;  //昵称 默认值null
    int mouth;     //年龄 默认值0
    double weight;  //体重 默认值0.0
    String sprcies;    //品种 默认值null
    //方法:跑动、吃东西
    public void run() {
        System.out.println("小猫会跑!");
    }
    //重载run方法。同一个类当中,相同方法名,不同参数类型的方法。
    public void run(String name) {
        System.out.println(name + "会跑!");
    }
    public void eat() {
        System.out.println("小猫吃东西!");
    }
}

  • 接着调用这个类
package net.kokwind.animal;

public class CatTest {

    public static void main(String[] args) {
        // 对象实例化操作
        Cat one=new Cat();
        one.name="猫猫";
        System.out.println(one.name);
        System.out.println(one.mouth);
        System.out.println(one.weight);
        System.out.println(one.sprcies);
        one.eat();
        one.run();
        one.run(one.name);
    }
}

输出

猫猫
0
0.0
null
小猫吃东西!
小猫会跑!
猫猫会跑!
2.6.5 对象实例化
  • 实例化对象的过程可以分为两部分:
  • 声明对象 Cat one是在栈里面
  • 实例化对象 new Cat(); 是在堆里面
  • 基本类型的变量在栈里面占一块内存
  • 引用类型的变量在栈和堆里面各占一块内存

image-20211209172534410

2.6.6 构造方法
  • 构造方法与类同名且没有返回值
  • 构造方法的语句格式
  • 只能在对象实例化的时候调用
  • 当没有指定构造方法时,系统会自动添加无参的构造方法
  • 当有指定构造方法,无论是有参、无参的构造方法,都不会自动添加无参的构造方法
  • 一个类中可以有多个构造方法
package net.kokwind.animal;
/**
 * 宠物猫类
 * @author Administrator
 *
 */
public class Cat {
    //属性:昵称、年龄、体重、品种
    String name;  //昵称 默认值null
    int mouth;     //年龄 默认值0
    double weight;  //体重 默认值0.0
    String sprcies;    //品种 默认值null

    //方法:跑动、吃东西
    public void run() {
        System.out.println("小猫会跑!");
    }
    //重载run方法。同一个类当中,相同方法名,不同参数类型的方法。
    public void run(String name) {
        System.out.println(name + "会跑!");
    }
    public void eat() {
        System.out.println("小猫吃东西!");
    }
    //添加有参数的构造方法,系统默认无参构造方法
    public Cat(String name,int mouth,double weight,String sprcies) {
        this.name=name;
        this.mouth=mouth;
        this.weight=weight;
        this.sprcies=sprcies;
        System.out.println(name+"构造方法");
    }
}
--------------------------------------
package net.kokwind.animal;

public class CatTest {

    public static void main(String[] args) {
        // 对象实例化操作
        Cat one=new Cat("猫猫",2,1000,"英国短毛猫");
        System.out.println(one.name);
        System.out.println(one.mouth);
        System.out.println(one.weight);
        System.out.println(one.sprcies);
        one.eat();
        one.run();
        one.run(one.name);
    }
}

输出:

猫猫构造方法
猫猫
2
1000.0
英国短毛猫
小猫吃东西!
小猫会跑!
猫猫会跑!

2.7 封装

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

  • 特点: 1、只能通过规定的方法访问数据 2、隐藏类的实例细节,方便修改和实现

自动生成get/set方法,点击右键如图:

image-20211210085155247

image-20211210085344598

示例:

package net.kokwind.animal;
/**
 * 宠物猫类
 * @author Administrator
 *
 */
public class Cat {
    //属性:昵称、年龄、体重、品种
    //封装的特点:1修改属性的可见性--private 限定只能在当前类内访问
    private String name;  //昵称 默认值null
    private int mouth;     //年龄 默认值0
    private double weight;  //体重 默认值0.0
    private String sprcies;    //品种 默认值null

    //2.创建get/set方法
    public void setName(String name) {
        this.name=name;
    }

    public String getName() {
        return name;
    }

    public void setMouth(int mouth) {
        if(mouth>0) {
            this.mouth=mouth;
        }else {
            System.out.println("mouth的值设置错误");
        }   
    }

    public int getMouth() {
        return mouth;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public String getSprcies() {
        return sprcies;
    }

    public void setSprcies(String sprcies) {
        this.sprcies = sprcies;
    }

    //方法:跑动、吃东西
    public void run() {
        System.out.println("小猫会跑!");
    }
    //重载run方法。同一个类当中,相同方法名,不同参数类型的方法。
    public void run(String name) {
        System.out.println(name + "会跑!");
    }
    public void eat() {
        System.out.println(name+"吃东西!");
    }

    //添加有参数的构造方法,系统默认无参构造方法
    public Cat(String name,int mouth,double weight,String sprcies) {
        this.name=name;
        this.mouth=mouth;
        this.weight=weight;
        this.sprcies=sprcies;
        System.out.println("构造方法中猫的名字是"+name+",年龄"+mouth+"个月,体重"+weight+"公斤,品种是"+sprcies);
    }
}
--------------------------------
package net.kokwind.animal;

public class CatTest {

    public static void main(String[] args) {
        // 对象实例化操作
        Cat one=new Cat("猫猫",-2,1000,"英国短毛猫");
        one.setName("小花");
        one.setMouth(-2);
        System.out.println("猫的名字叫"+one.getName());
        one.eat();
    }
}

输出:

构造方法中猫的名字是猫猫,年龄-2个月,体重1000.0公斤,品种是英国短毛猫
mouth的值设置错误
猫的名字叫小花
小花吃东西!

2.8 包

  • 管理Java文件
  • 解决同名文件冲突
  • 语法:package 包名;
  • 必须放在Java源文件中的第一行
  • 一个Java源文件中只能有一个package语
  • 包名全部英文小写
  • 包名全部英文小写

  • 导入包

  • import 包名.类名 import net.kokwind.*;

  • 常用系统包

  • java.lang 包含java语言基础的类
  • java.util 包含java语言中各种工具类
  • java.io 包含输入、输出相关功能的类

2.9 继承

2.9.1 继承
  • 一种类与类之间的关系
  • 使用已存在的类的定义作为基础建立新类
  • 新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类
  • 父类 基类
  • 子类 派生

  • 编写父类

class Animal{
  //公共的属性和方法
}
  • 编写子类,继承父类
class Dog Extends Anomail{
  //子类特有的属性和方法
}
  • 示例:
package net.kokwind.animal;

public class Animal {
    private String name;
    private int mouth;
    private String species;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getMouth() {
        return mouth;
    }
    public void setMouth(int mouth) {
        this.mouth = mouth;
    }
    public String getSpecies() {
        return species;
    }
    public void setSpecies(String species) {
        this.species = species;
    }

    //吃东西
    public void eat() {
        System.out.println(this.getName()+"吃东西");
    }
}
package net.kokwind.animal;
/**
 * 宠物猫类
 * @author Administrator
 *
 */
public class Cat extends Animal {
    private double weight;

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    //跑动的方法
    public void run() {
        System.out.println(this.getName()+"快跑");
    }
}
package net.kokwind.animal;

public class Dog extends Animal {
    private String sex;

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void sleep() {
        System.out.println(this.getName()+"在睡觉");
    }
}
package net.kokwind;

import net.kokwind.animal.Cat;
import net.kokwind.animal.Dog;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Cat one=new Cat();
        one.setName("花花");
        one.setSpecies("中华田园猫");
        one.eat();
        one.run();
        System.out.println("===============");
        Dog two=new Dog();
        two.setName("凡凡");
        two.setMouth(12);
        two.eat();
        two.sleep();
    }
}

输出:

花花吃东西
花花快跑
===============
凡凡吃东西
凡凡在睡觉
  • 方法的重写

  • 语法规则:

    • 有继承关系的子类中定义
    • 方法名相同,参数列表相同(参数顺序、个数、类型)
    • 与方法的参数名无关
  • 复习方法的重载:

    • 同一个类中
    • 方法名相同,参数列表不同
    • 方法的返回值和访问修饰符任意
package net.kokwind.animal;

public class Dog extends Animal {
    private String sex;

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void sleep() {
        System.out.println(this.getName()+"在睡觉");
    }
    //方法的重载
    public void sleep(String name) {
        System.out.println(name +"开始睡觉了");
    }

    //重写狗吃东西的方法
    public void eat() {
        System.out.println(this.getName()+"最近没食欲,不吃东西");
    }
}
package net.kokwind;

import net.kokwind.animal.Cat;
import net.kokwind.animal.Dog;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Cat one=new Cat();
        one.setName("花花");
        one.setSpecies("中华田园猫");
        one.eat();
        one.run();
        System.out.println("===============");
        Dog two=new Dog();
        two.setName("凡凡");
        two.setMouth(12);
        two.eat();
        two.sleep("齐齐");
    }
}

输出:

花花吃东西
花花快跑
===============
凡凡最近没食欲,不吃东西
齐齐开始睡觉了
2.9.2 访问修饰符
运算符 本类 同包 子类 其它
private
默认
protected
public
2.9.3 super
  • 子类访问父类成员

  • 访问父类成员方法 super.print();

  • 访问父类属性 super.name;

  • 父类的构造方法不可以被继承、不允许被重写

2.9.4 final
  • 修饰类表示不允许被继承
  • 修饰方法表示不允许被子类重写
  • final修饰的方法可以被继承
  • 不能修饰构造方法
  • 修饰变量表示不允许修改
  • 可配合static使用
  • 使用final修饰可以提高性能,但会降低可扩展性