JAVASE整理知识点

本文详细介绍了Java的基础知识,包括计算机语言的发展历程、Java的特性、核心机制,以及开发Java程序的步骤。内容涵盖Java命令、类与对象、数据类型、异常处理、多线程、反射、泛型、注解、网络编程等多个方面,旨在帮助读者全面理解Java语言及其应用。
摘要由CSDN通过智能技术生成

基础知识

计算机的组成 :

硬件 : 能看得见, 摸得着的电子元器件.

软件 : 存储在硬件中的数据(可以执行) : 指令+数据的集合.

系统软件 : 操作系统 OS, 让用户能够方便的使用电脑硬件.(没有国产OS)

应用软件 : 为了完成某种功能的软件. 学习java目标就是应用软件.

人机交互 : 人通过OS来使用电脑.

GUI :图形化界面

CLI :命令行, 只有一个控制台(console).

在windows中启动控制台 :

Win+r => cmd 回车(动令)

目录 : 用于管理批量的子文件和子目录.

C:\Users\pauliuyou>_

‘>’称为前导符

C:\Users\pauliuyou这是一个目录, 称为当前目录,也称为工作目录.

dir 目录的意思, 作用是列出当前目录下的内容 : 包括子文件和子目录.

切换盘符 : 举例d; 切换到D盘

Md (make directory) 目录名1 目录名2 在当前目录中创建新子目录

把右面的称为命令行参数, 作用是给命令传递进一步的信息数据.

Md 新目录名1 新目录名2

Cd (change directory) 改变当前工作目录.

Cd 目标目录

2个特殊目录 :

  • . 点目录表示当前目录
  • … 点点目录表示当前目录的上级目录(父目录)
  • \ 称为反斜杠
  • / 称为斜杠
  • \的作用是用于表示父子关系.
  • /也可以, 并且在linux系统中必须使用/来表示目录分隔.

路径(path) : 一条路, 这条路的尽头是一个文件或目录.(也称为地址)

Cd MyWork\JavaSE\day01\code

相对路径 : 总是从当前目录为出发点. .\MyWork\JavaSE\day01\code 就是相对路径, 相对路径的前面”./”可以省略

绝对路径 : 以根目录为开始,为出发点的路径 D:\MyWork\JavaSE\day01\code 就是绝对路径. 特点 : 不会出错

  • cd/ 直接回到当前盘的根目录
  • cd… 返回上一级目录
  • cd…/…返回到上两级目录
  • Cd /d +路径 可以任意切换目标目录
  • exit 退出命令行

计算机语言发展历程

第一代 : 打孔机 面向硬件开发.

第二代 : 汇编语言 面向CPU开发, 缺点: 不能跨CPU

第三代 : C/C++, 面向OS开发, 优点 : 效率高, 缺点 : 不能跨OS

第四代 : java , 面向VM开发, 优点 : 不受OS影响. 缺点 : 相对汇编稍慢

Java的8个特性

  1. 简单 : 相对于c/c++
  2. 面向对象 : 相对于面向过程, 面向过程关注问题解决的步骤, 面向对象关注是具有功能的对象
  3. 分布式 : 基于网络的多主机协助.
  4. 健壮 : 强类型(所有数据必须有类型), 异常处理, 垃圾收集(内存中应该被释放的空间没有释放. 把空间标记为可用状态就是清理垃圾) GC.
  5. 安全 : 所有java程序必须通过类加载器
  6. 跨平台 : 所有java程序中的指令都是面向VM的. 只要有VM, java程序就能执行
  7. 性能好 : 是编译型比解释型要快.
  8. 多线程 : 提升服务器的吞吐量, 最大化利用CPU.

Java两种核心机制

  1. Java虚拟机(Java Virtal Machine)
  2. 垃圾收集机制(Garbage Collection)

运行java程序的最低要求是 JRE

JRE = JVM + 核心类库

开发java程序必须要求有JDK

JDK = JRE + 开发工具

常用java开发命令

Javac 编译

Java 运行

开发java程序的步骤

  1. 创建.java源文件
  2. 编译.java源文件, 生成.class字节码文件
  3. 运行.class字节码文件

开发程序具体步骤

  1. 找到d:\MyWork\JavaSE\day01\code目录, 在code目录中右击新建一个文本文件, 改名为Hello.java

  2. 右击此文本文件, 使用notePad++打开编辑

注意点 : 编辑文件时, 大小写敏感, 所有标点符号必须使用英文半角的标点符号

  1. 打开命令行窗口, 切换当前工作目录为刚才的code目录中, 并确保刚才编辑的.java文件就在当前目录下.

D:

Cd mywork\javase\day01\code

  1. 使用命令javac Hello.java 编译源文件, 编译的结果是生成Hello.class字节码文件

  2. 仍然还是在当前目录中, 使用命令java Hello 执行程序

注意点 : java Hello后面的内容不要加后缀

解决乱码

  1. 全选并复制所有内容

  2. 点击菜单”格式” 选中 “以ANSI格式编码”

  3. 此时会全乱, 把所有内容删除,重新粘贴刚才复制的内容

  4. 确保右下角的编码方式为ANSI, 如果是utf8重复刚才的步骤

: java程序的基本单位

方法 : java程序的基本功能单位

语句 : java程序的最小执行单位

类 {

​ 方法1 {

​ 语句1;

​ 语句2;

​ ……

}

​ 方法2 {

}

​ ….

}

主类 : 包含主方法的类称为主类

非主类 : 不包含主方法的类称为非主类

一个源文件中可以写多个类, 编译以后的结果是每个类都有自己独立的.class文件

但是一个源文件中只能写一个公共类, 非公共类随便, 主类随便

Java程序的执行过程 :

java 主类

java命令一执行, 就会动态地创建一个JVM出来

主类的作用就是告诉JVM加载哪个类并执行, 加载主类以后, 再找到主类的入口方法, 执行入口方法.

主方法一旦执行完毕, JVM销毁, 程序退出

小结第一个程序 :

  1. Java源文件以“java”为扩展名。源文件的基本组成部分是类(class),如本类中的HelloWorld类。
  2. 一个源文件中最多只能有一个public类。其它类的个数不限,如果源文件包含一个public类,则文件名必须按该类名命名。
  3. Java应用程序的执行入口是main()方法。它有固定的书写格式:public static void main(String[] args) {…}
  4. Java语言严格区分大小写。
  5. Java方法由一条条语句构成,每个语句以“;”结束。
  6. 大括号都是成对出现的,缺一不可。

注释

// 单行注释 : 只对当前行有效

/*

多行注释 : 可以给多行文字进行注释, 有头有尾

​ 再来一行, 多行注释不可以嵌套!!

*/

/**

public 是公共的, 是一个形容词, 用于修饰后面的东西.

class 是类, 是一个关键字, 用于声明一个类. 类是java程序的基本单位.

Hello 是类名, 通常类名首字母大写.

类名后面的{}及其中的内容称为 类体

类 = 类头(类签名) + 类体;

主类 : 包含主方法的类就是主类

被public修饰的类 称为 公共类

一个源文件中必须只能有一个公共类, 公共类的类名必须和文件名一致.

*/

public class Hello{

/**

下面的这个东西称为方法, 也称为函数, 是java程序的一个独立的功能单位.

类中包含方法, 方法必须写在类中.

public 是公共的, static 静态的 都是修饰符

void main(String[] args) 方法签名, main称为方法名.

参数后面的一对{}及其中的内容称为方法体.

方法 = 方法签名 + 方法体

方法必须写在类中, 并且不可以嵌套.

此方法称为主方法, 也称为入口方法, 程序总是从main方法开始执行.

写法固定, 必须背会它!!!

*/

public static void main(String[] args){

​ // 语句 : java程序的最小执行单位, 并且要求必须以;结尾

​ // 方法中可以包含语句 , 并且可以包含多条语句.

​ System.out.println(“这里自由发挥,语句1”);

​ System.out.println(“语句2”);

​ System.out.println(“语句3”);

​ System.out.println(“语句4”);

}

/* 方法在同一个类中不可以重复定义!!

public static void main(String[] args) {

​ System.out.println(“我也是main”);

}*/

public static void method1() {

​ System.out.println(“method1()…”);

​ }

}

// 非公共类 : 没有被public修饰的类

class Hello2 { // 非主类, 不包含主方法

​ public static void test2() {

​ System.out.println(“test2()…”);

​ }

}

//public class Hello3 // Hello3不能被public修饰, 因为公共类的类名必须和文件名一致

class Hello3 {

​ public static void main(String[] args) {

​ System.out.println(“Hello3 main()…”);

​ }

}

注意点 : 对于程序的任何修改都必须要重新保存文件, 并重新编译新的.class文件.

NotePad++快捷操作

  • Ctrl + a 全选
  • Ctrl + c 复制
  • Ctrl + v 粘贴
  • Ctrl + x 剪切
  • Ctrl + z 撤销
  • Ctrl + y 重做
  • Ctrl + s 保存
  • Shift + tab 把选中的内容整体左移
  • Tab 把选中的内容整体右移
  • Ctrl + l 删除当前行
  • Ctrl + d 快速复制当前

JAVA基本语法

关键字 : 在java程序中有特殊含义和作用的单词. 不要直接使用关键字作为标识符

保留字 : 在c/c++中是关键字, 但是在java中目前还不是, 但是将来有可能会成为关键字.

​ 不要直接使用保留字作为标识符

标识符 : 用于标识某个东西的符号(是一个名字)

​ 通常比如标识类, 变量, 方法….

定义合法标识符规则:(必须遵守)

  1. 组成由26个字母大小写, 0~9, _和$

  2. 数字不可以开头, 比如3A这个类名不合法, 但是A3就是合法的

  3. 不可以直接使用关键字和保留字, 但是可以包含关键字和保留字

  4. 大小写敏感, 最长65535

  5. 不可以包含空格

java中的名称命名规范(可以不遵守,但是最好遵守)

包名 : 全部小写

类名 : 首字母必须大写, 后面的单词首字母也大写

MyClassName 驼峰命名法

变量,方法名 : 首字母必须小写, 后面的单词首字母大写

myVarName

**常量名 😗*全部大写,单词之间用_隔开

​ MY_CONST_NAME唯一允许使用_的地方.

编程风格

缩进 : 使用tab

运算符 : 两加都加上空格 4*3/2+5, 4 * 3 / 2 + 5

{}块是行尾风格

变量

内存中的一块区域, 用于保存数据.

此区域必须要命名, 如果没有名字, 我们没有办法定位它.

此区域必须要被特定的数据类型约束, 数据类型可以决定空间大小,并且决定此空间中的数据可以做什么

变量的两个最重要的要素, 就是 数据类型变量名

变量必须先声明, 后使用.

数据类型

Java是一种静态的强类型语言。对于每一个常量、变量、形参、返回值等类型都是非常严格

数据类型作用 :

  1. 决定了空间的大小.

  2. 决定了里面的数据可以做什么.

数据类型分类
基本数据类型
(内存区域中保存的是数据本身) 8种

1.数值型:

​ 整数型:

​ byte:1字节 -128~127

​ short:2字节 -32768~32768

​ int:4字节 -20多亿~20多亿

​ long:8字节 900万亿亿

​ 浮点型:

​ float:4字节 -1038~1038

​ double:8字节 10^308

2.字符型:

​ char:2字节

3.布尔型:

​ boolean:1字节(true false)

​ false 为0 true 为真,但是只能用字面量,不能赋值

引用数据类型
内存区域中保存的是别的数据的地址

按照声明的位置划分:

局部变量:

  • 方法体{}中
  • 方法签名的()中的形参列表
  • 代码块{}中

成员变量:

  • 在类中,但是在方法和代码块外面
    • 有static修饰的成员变量称为静态变量,所有对象共享
    • 没有有static修饰的成员变量称为实例变量,每一个对象独立
public class VariableType {
   
    static int a;//成员变量之一:静态变量
    int b;//成员变量之一:实例变量
    String info;//成员变量之一:实例变量
    Student stu;//成员变量之一:实例变量

static{
   
    //静态代码块,后面讲
    int c = 1;//局部变量
}

{
   
    //构造代码块,后面讲
    int d = 1;//局部变量
}

//(String[] args) 局部变量
public static void main(String[] args) {
   
    int num = 10;//num局部变量,是基本数据类型的局部变量
    String str = "hello";//str是局部变量,是引用型局部变量
    Student student = new Student("张三");//student是局部变量,是引用型局部变量
}

//int a, int b局部变量
public static int sum(int a, int b){
   
    return a + b;
}

//(int x, int y)局部变量
public void swap(int x, int y){
   
    int temp = x;//局部变量
    x = y;
    y = temp;
}
}

各种数据类型的使用:

不同的数据使用不同的数据类型来保存, 取决于数据的上限是多少.

变量 : 内存区域中的数据可以修改的量

常量 : 内存区域中的数据不允许修改的量, 包括 字面量(写出来多少就是多少), 和 被final修饰的量:

200, 5.2, false, true, null, ‘a’, “ccc”

赋值符号左侧必须是变量, 如果是常量不可以!!!

范围大的变量是可以接收范围小的量值, 会发生自动数据类型转换

范围小的变量接收范围大的量值时, 必须强制类型转换, 强制类型转换有风险!!!

整数字面量默认使用的类型是int型.

浮点数字面量默认使用的类型是double型(8字节)

数值型范围大小排序, 从大到小

double > float > long > int > short > byte

​ > char

任意非long整数变量作运算, 结果总是int型.

多种不同类型的变量混合运算时, 类型会升级为最大的类型

Char 是基本数据类型, 在内存中占用2个字节, 保存的是某个字符的Unicode码值,

它的范围是0~65535. 所以本质上来讲它也是整数, 可以参与整数和浮点数运算.

Charshort,byte不兼容, 互相赋值时, 必须强制类型转换.

Boolean 只允许两个值, 一个true, 一个是false

进制

计算权值以10为底, 这样的数称为10进制数.

10进制没有10, 逢10进1, 最大是9

X进制, 计算权值是以X为底的n次幂. 逢X进一

19 + 1 = 20

二进制 : 计算权值是以2为底的n次幂, 逢2进1

十六进制 : 计算权值是以16为底的n次幂, 逢16进1

进制转换:

​ 十进制 二进制 十六进制

​ 0 0000 0

​ 1 0001 1

​ 2 0010 2

​ 3 0011 3

​ 4 0100 4

​ 5 0101 5

​ 6 0110 6

​ 7 0111 7

​ 8 1000 8

​ 9 1001 9

​ 10 1010 A

​ 11 1011 B

​ 12 1100 C

​ 13 1101 D

​ 14 1110 E

​ 15 1111 F

每个十六进制数都可以机械地转化为4个比特的二进制数.

每4个位的二进制数可以转换成一个十六进制数.

0110 => 0x6

0101 1101 => 0x5D

2.变量按照数据类型

分为基本数据类型变量和引用数据类型变量

列出8种基本数据类型, 并写出基本数据类型变量和引用数据类型变量的区别.

1) 基本数据类型 : 内存区域中保存数据本身
数值型

​ 整数:byte short int long char

​ 浮点数:float double

布尔型

​ boolean

2) 引用(Reference)数据类型 : 内存区域中保存其他数据的地址

​ 地址 : 内存中某个字节的编号. 本质上是一个正整数…

​ 引用变量占用的空间取决于JDK位数 : 如果是32位JDK, 它用4字节整数来保存

​ 如果是64位JDK, 它用8字节整数来保存地址.

​ 地址为0的地址是一个无效地址, 称为null

3 .列出变量使用注意事项

  1. 先声明, 后使用.

  2. 变量必须要有数据类型和变量名

  3. 变量中数据只能在其数据范围内变化.

  4. 变量有其作用范围, 作用范围由声明语句所隶属的一对{}.

  5. 同一个作用范围内, 变量不能重复声明(declare)

  6. 变量必须初始化(出生时进行的赋值)才能使用

​ int a;

​ System.out.println(a);

4.判断下列的带( )行的对错

​ int i1 = 20;

​ short s1 = i1; (F)

​ char c1 = 97; (T) char c1 = ‘a’;

​ char c2 = ‘我’ - ‘你’;(T)

​ char c3 = (char)(c1 - 32); //可以达到小写变大写的效果(T)

​ float f1 = i1;(T)

​ long l1 = 234234239933L;(F) 整数字面量默认使用4字节的int来保存的.

​ f1 = l1 * 20;(T)

​ double d1 = .342;

​ d1 = i1 * f1 * l1;(T) // 混合运算时, 结果类型是范围最大的那个类型

​ l1 = f1 / 10000;(F)

​ boolean b1 = (boolean)1;(F)

变量的分类 :

  1. 按照数据类型来分类

a) 基本数据类型 (保存数据本身)

b) 引用数据类型 (保存对象地址)

​ 2) 按照声明语句的位置来分类

​ 局部变量 : 声明在方法中的变量

​ 范围小, 寿命短.

成员变量 : 声明在类中方法外的变量

范围大, 寿命长

进制

十进制 : 只有0~9, 逢10进1, 一个数计算权值时以10为底n次幂

二进制 : 只有0和1, 逢2进1, 权值计算以2为底

十六进制 : 只有0~F, 逢16进1, 权值计算以16为底

计算机底层的所有数据全是二进制补码.

底层区分正负数使用的是一个数的最高位, 如果最高位为0, 说明这个数是正数

如果最高位符号位值为1, 说明这个数是负数.

补码 :

正数的补码就是自身.

0011 1101 -> 这是一个正数

0x3D -> 3*16+13 = 61, 所以0011 1101就是61

负数的补码 :

由它的相反数全部取反+1得到

1110 1001 -> 这是一个负数, 并且它一定是补码, 负多少?

还原它的相反数就可以.

-1 : 1110 1000

取反 : 0001 0111 => 0x17 => 23

所以1110 1001就是-23

运算符

左移 : 左移一位是一个数*2

右移 : 右移一位是一个数/2

与运算(&) : 对应二进制上有0就是0, 只有全是1的结果才是1

或运算(|) : 对应二进制上有1就是1, 只有全是0结果才是0

整数除法: 注意点 : 小数部分直接丢弃, 所以有可能会有精度丢失!!

取模 % 应用场景

  1. M % N结果总是在[0~n-1], 可以让一个未知数落在一个已经的范围内.

  2. M % N 结果为0, 说明M可以被N整除

M % N 结果不为0, 说明M不能被N整除.

  1. M % 2 结果为0, 说明这个数是偶数.

M % 2 结果不为0, 说明这个数是奇数

自增 : 自已就可以变化. 是单目运算.

Int n = 5;

n++; 后加加, 先用后加

等效于 n = n + 1;

++n; 前加加, 先加后用

等效于 n = n + 1;

Int a = 8;

Int b = a++; // b:8, a:9

Int x = 11;

Int y = ++x; // x:12, y:12

赋值运算符 :

  1. ​ 优先级最低, 所以总是最后执行
  2. ​ 它是从右向左的逻辑, 右面的值没有确定, 不可以向左走.
  3. ​ 看到赋值操作心里要紧张, 因为它一定会改变变量的值.
  • 累操作, 累加, 累减
  • +=, -=, *=, /= 不会引发数据类型的变化, 所以是安全的.
比较运算的结果总是布尔值
  1. == 比较是否相等
  2. != 比较是否不等
  3. 以上和!=可用于所有类型的数据. 但是对象之间, 比较的是对象的地址值.
比较大小的操作 :

>, >=, <, <= 只适用于基本数据类型中的数值型

布尔类型不可以比大小, 还有对象不能比大小.

3 < x < 6

3 < x结果是boolean, 再让boolean和6比大小.

应该写成

3 < x && x < 6

&& 短路与 :

只要有假结果一定是假

|| 短路或 :

只要有真结果一定是真

优先级 :

最高的是. 和(), 最低的是 =

逻辑与算符

& 逻辑与

| 逻辑或

! 逻辑非

&& 短路与

|| 短路或

^ 逻辑异或 (追求的是 “异”)

三元运算符

格式:
(条件表达式)? 表达式1:表达式2;

条件表达式 为true,运算后的结果是表达式1;
条件表达式 为false,运算后的结果是表达式2;

表达式1和表达式2为同种类型
三元运算符与if-else的联系与区别:
1)三元运算符可简化if-else语句
2)三元运算符要求必须返回一个结果。
3)if后的代码块可有多个语句

if-else语句

if语句三种格式:

  1. if (条件表达式) {
    执行代码块;
    }

  2. if (条件表达式) {
    执行代码块;
    } else {
    执行代码块;
    }

  3. if (条件表达式1) {
    执行代码块1;
    } else if (条件表达式2) {
    执行代码块2;
    } else if (条件表达式3) {
    执行代码块3;
    }
    …… else {
    执行代码块n;
    }

switch语句

switch(变量){
case 常量1:
语句1;
break;
case 常量2:
语句2;
break;
… …
case 常量N:
语句N;
break;
default:
语句;
break;
}

switch语句相关规则

1.switch(表达式)中表达式的返回值必须是下述几种类型之一:byte,short,char,int,String, 枚举;

2.case子句中的值必须是常量,且所有case子句中的值应是不同的;

3.default子句是可任选的,当没有匹配的case时,执行default

4.break语句用来在执行完一个case分支后使程序跳出switch语句块;如果没有break,程序会顺序执行到后面第 一个break语句或直接执行到switch结尾(这种现象称为穿透)

2.基本数据类型

8种基本数据类型:

  1. 数值型

    1. 整数

    byte 1000 0000, 0111 1111 => 0x80, 0x7F

    short 1000 0000 0000 0000, 0111 1111 1111 1111 => 0x8000, 0x7FFF

    char 0000 0000 0000 0000, 1111 1111 1111 1111 => 0x0000, 0xFFFF

    int 1(31个0), 0(31个1) => 0x80000000, 0x7FFFFFFF

    long 1(63个0), 0(63个1) => 0x8000000000000000, 0x7FFFFFFFFFFFFFFF

    1. 浮点数

    float

    double

  2. 布尔型

    boolean

3.计算下列结果, 分析过程

​ 只需要计算到十六进制形式即可

​ byte a = 0x6B;

​ byte b = 0x5D;

​ // 0110 1011&

​ // 0101 1101=

​ // 0100 1001 => 0x49

​ System.out.println(a & b);

​ // 0110 1011 |

​ // 0101 1101 =

​ // 0111 1111 => 0x7F

​ System.out.println(a | b);

​ // 0110 1011 ^

​ // 0101 1101 =

​ // 0011 0110 => 0x36

​ System.out.println(a ^ b);

4.运算符%的作用和实际的应用

​ %的作用是取余或取模.

​ 1) M % N 结果总是0~N-1, 可以让一个未知数落在一个已知范围内

​ 2) M % N 结果如果为0, 说明M可以被N整除.

​ 3) M % 2 结果如果为0, 说明M是偶数, 如果结果不为0, 说明M是奇数

5.判断:

1)相同字面量十六进制表示的数比十进制要大, 对或错? 为什么?

​ 10以内是相等的. 0x3, 3

​ 其他的情况会大

​ 0x80, 和 80

​ 如果0x80是byte型, 它实际是-128, 80

​ 十六进制本身不承载任何数据类型信息, 只是忠实的反映二进制.

2)if else if else if else 语句中, 如果同时有多个条件都为true, 那么将会有多个语句块被执行,

​ 错, 这是分支, 一定只有一个分支被执行, 不可能执行多个语句块

3)switch case case default 语句中, 如果同时有多个条件都为true, 那么将会有多个语句块被执行

​ 错, case 不允许重复相同.

6.变量的分类法 :

  1. 按照数据类型来分 : 决定存什么

    1. 基本数据类型 : 内存区域中保存数据本身

    2. 引用数据类型 : 内存区域中保存对象地址. (某个字节的编号)

  2. 按照声明语句位置来分 : 决定它的使用范围

​ 1) 局部变量 : 在方法中声明

​ 范围小, 寿命短

​ 2) 成员变量 : 在类中方法外声明

​ 范围大, 寿命长

循环结构

循环语句功能

​ 在某些条件满足的情况下,反复执行特定代码的功能

循环语句的四个组成部分

​ 初始化部分(init_statement)
​ 循环条件部分(test_exp)
​ 循环体部分(body_statement)
​ 迭代部分(alter_statement)

循环语句分类

​ while 循环
​ do/while 循环
​ for 循环

while循环语句

语法格式

[初始化语句]
while( 布尔值测试表达式){
语句或语句块;
[更改语句;]
}

应用举例

public class WhileLoop {
   
		        public static void main(String args[]){
   
        		int result = 0;
			int i=1;
			while(i<=5) {
   
			        result += i;
            	       	        i++;
			}
			System.out.println("result=" + result);
		         }
		} 

do-while循环语句

语法格式

[初始化语句]
do{
语句或语句块;
[更改语句;]
}while(布尔值测试表达式);

应用举例

public class WhileLoop {
   
		        public static void main(String args[]){
   
        		  int result = 0,  i=1;
			  do {
   
			         result += i;
           		         i++;
			  } while(i<=5);
			  System.out.println("result=" + result);
		       }
		}  

注意要点

先执行语句一次,再判断条件

for循环语句

语法格式

for (初始化表达式①; 布尔值测试表达式②⑤⑦; 更改表达式){
语句或语句块③⑥ ;

应用举例

public class ForLoop {
   
		public static void main(String args[]){
   
		          int result = 0;
		          for(int i=1; i<=5; i++) {
   
			  result += i;
		          }
  	          System.out.println("result=" + result);
		}
	} 

注意要点

先判断条件,再执行语句

嵌套循环

  • 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for ,while ,do…while均可以作为外层循环和内层循环。
  • 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环。
  • 设外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n次。

嵌套循环练习

九九乘法表

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


空心等腰三角形

//扩展 : 打印高度为n的空心的等腰三角形.
class HomeWork41{
   
	public static void main(String[] args){
   
		int n = Integer.parseInt(args[0]);
		for(int i = 0;i < n;i++){
   
			for(int j = 0; j < n - i - 1;j++){
   
				System.out.print(" ");
			}
			for(int j = 0;j < 2*i+1;j++){
   
				//第n行中间不加空格,所以i<n-1;
				//j==0 && j==2i时,两个腰边有*,所以在他们之间打出空格的条件如下
				if ((i < n-1) && j > 0 && j < 2*i ){
   
					System.out.print(" ");
				}else{
   
					System.out.print("*");
				
				}
				
			}
			System.out.println();
		}
	}
}

输入年、月、日,判断这一天是当年的第几天

先不考虑非法值输入

注:判断一年是否是闰年的标准:

​ 1)可以被4整除,但不可被100整除

​ 2)可以被400整除

例如:1900,2200等能被4整除,但同时能被100整除,但不能被400整除,不是闰年

public class TestExer11{
   
	public static void main(String[] args){
   
		int year = Integer.parseInt(args[0]);
        int month = Integer.parseInt(args[1]);
        int day = Integer.parseInt(args[2]);
		

	//判断这一天是当年的第几天==>从1月1日开始,累加到xx月xx日这一天
	//(1)[1,month-1]个月满月天数
	//(2)第month个月的day天
	//(3)单独考虑2月份是否是29天(依据是看year是否是闰年)
	
	//2、声明一个变量days,用来存储总天数,直接初始化为day,这样就不用再加day天了
	int days = day;
	
	//3、累加[1,month-1]个月满月天数
	switch(month){
   
		case 12:
			//累加的1-11月
			days += 30;//这个30是代表11月份的满月天数
			//这里没有break,继续往下走
		case 11:
			//累加的1-10月
			days += 31;//这个31是代表10月的满月天数
			//这里没有break,继续往下走
		case 10:
			days += 30;//9月
		case 9:
			days += 31;//8月
		case 8:
			days += 31;//7月
		case 7:
			days += 30;//6月
		case 6:
			days += 31;//5月
		case 5:
			days += 30;//4月
		case 4:
			days += 31;//3月
		case 3:
			days += 28;//2月
			//4、在这里考虑是否可能是29天
			if(year%4==0 && year%100!=0 || year%400==0){
   
				days++;//多加1天
			}
		case 2:
			days += 31;//1月
	}
	
	//5、输出结果
	System.out.println(year + "年" + month + "月" + day + "日是这一年的第" + days + "天");
}

}	 

特殊流程控制语句

break 语句

break语句用于终止某个语句块的执行
{ ……
break;
……
}

break语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块

class BreakTest2 {

public static void main(String[] args) {
   
	// 循环可以加标签, 标签的命名: 只要是合法标识符就可以
	l1 : for (int i = 0; i < 10; i++) {
   
		l2 : for (int j = 0; j < 5; j++) {
   
			System.out.println(" j : " + j);
			if (j == 2) {
   
				//break; // 默认中断离我最近的循环.
				break l1; // 中断指定标签对应的循环.输出0 1 2以后,循环终止
			}
		}
		System.out.println("i : " + i);
	}
}

continue 语句

  • continue语句用于跳过某个循环语句块的一次执行
  • continue语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环

continue 语句用法

public class ContinueTest {
   	

public static void main(String[] args) {
   
	// continue : 继续, 跳过循环的某次执行, 直接进入下一次执行. 对于循环的破坏力度不大
	// 只能用于循环
	for (int i = 0; i < 100; i++) {
   
		if (i % 2 == 0) {
   
			continue; // continue暗含的逻辑, 应该向下走, 但是出现小意外, 导致得跳过.
		}
		System.out.println("i : " + i);
	}
}

}

return 语句

  • return:并非专门用于结束循环的,它的功能是结束一个方法。当一个方法执行到一个return语句时,这个方法将被结束。
  • 与break和continue不同的是,return直接结束整个方法,不管这个return处于多少层循环之内

特殊流程控制语句说明

  • break只能用于switch语句和循环语句中
  • continue 只能用于循环语句中
  • 二者功能类似,但continue是终止本次循环,break是终止本层循环
  • break、continue之后不能有其他的语句,因为程序永远不会执行其后的语句(有就会报错)
  • 标号语句必须紧接在循环的头部

方法(method)

方法(函数)的制造环节

方法(method) :

就是函数, 是java程序中的某个独立的功能的体现.
方法必须声明在类中, 并且方法不可以嵌套, 只能并列存在

方法的声明 :

修饰符 返回值类型 方法名(数据类型1 形参1, 数据类型2 形参2, 数据类型3 形参3....) {
   
		语句构成的方法体;
		return 返回值;
	}

方法 = 方法签名(不执行, 虽然不执行,但是重要, 因为它相当于方法的使用说明书API) + 方法体(执行);

形参 : 形式参数, 在方法声明时的数据, 但是此数据在声明时是没有值的, 没有参数不行, 同时参数的值是多少也没有影响.
形参就是变量, 是某个方法的局部变量.
返回值 : 方法的结果. 如果返回值类型是void, 表示方法没有返回值.

方法的使用环节 :

调用方法 : 方法名(实参列表); // 实参列表必须和形参列表匹配!!!
返回值 : 方法调用本身就是返回值. 返回值的接收只有一次机会.

最简单的方法 : 无返回值, 无参数, 即使是无参, 也不能省略().
无参方法在被调用时, 也不能省略()

方法调用注意点 :

  • 没有具体返回值的情况,返回值类型用关键字void表示,那么该函数中的return语句如果在最后一行可以省略 不写。
  • 定义方法时,方法的结果应该返回给调用者,交由调用者处理。
  • 方法中只能调用方法,不可以在方法内部定义方法。
  • 方法的返回值只有一次机会接收, 就是在调用时
  • 如果在方法中又调用了方法本身, 称为递归调用

方法代码练习实例:

public class MethodTest {
   	

public static void test() {
   
	System.out.println("test()....");
	//return; // 如果方法的返回值为void, 并且在最后有return, 可以省略这个return
}

// 完成一个功能, 两个整数求和. 一个方法可以被多次调用, 并且每次的参数可以不同.
// 方法的每次调用都是一个独立的执行, 互不相干!!!
public static int add(int a, int b) {
   
	System.out.println("add (int a, int b)...");
	int c = a + b;
	return c; // 返回的是c中的值.
}

public static void main(String[] args) {
   
	System.out.println("main begin");
	int x = add(10, 20); // 10称为实参, 20也是实参, 在调用时, 会把10给方法的a,  20给方法的b
	//System.out.println(c);
	System.out.println(x);
	System.out.println(add(50, 80)); // add先执行, println后执行
	// 如果方法没有返回值, 禁止接收!!!!
	//int y = test(); // 无参方法的调用
	test(); // ()如果跟在一个东西后面, 99%可能性是方法调用!! ()是方法的标志.{}是块的标志, []是数组的标志
	// 没有返回值的方法, 禁止打印!!!!!
	//System.out.println(test());
	
	System.out.println("main end");
}

}

方法的重载

重载(Overload) :

同一个类中, 方法可以有多个重名的, 只要参数不同即可, 这样的一系列方法形成重载.
参数不同 体现为 :

参数的个数不同, 参数的类型不同, 参数的顺序不同.

重载和方法的返回值没有关系 .

如何区分是调用哪个方法, 由实参类型来决定

实参和形参之间是有匹配度的. 优先完全匹配, 再兼容匹配.

方法重载的目的 :

功能类似的参数不同的方法, 用同一个方法名来描述, 对于调用者来说简单, 只需要记一个名字(方法的提供者麻烦)

重载代码练习实例:

public class OverLoadTest {
   	

public static int add(int a, int b) {
   
	System.out.println("add(int a, int b)...");
	int c = a + b;
	return c;
}

public static int add(int a, int b, int c, int d) {
   
	System.out.println("add(int a, int b, int c, int d)");
	int e = a + b + c + d;
	return e;
}

public static double add(double a, int b) {
   
	System.out.println("add(double a, int b)");
	double c = a + b;
	return c;
}

/* 此方法和上面的方法是冲突, 不是重载!!!!
public static double add(double b, int a) {
	System.out.println("add(double a, int b)");
	double c = b + a;
	return c;
}*/

public static double add(int a, double b) {
   
	System.out.println("add(int a, double b)");
	double c = a + b;
	return c;
}

public static byte add(byte a, byte b) {
   
	System.out.println("add(byte a, byte b)...");
	byte c = (byte)(a + b);
	return c;
}

public static void main(String[] args) {
   
	System.out.println(add((byte)10, (byte)30)); 
	System.out.println(add(10.2, 30)); 
	
	System.out.println(add(5, 8));
	
	System.out.println(100); // int 
	System.out.println("abc"); // String 
	System.out.println(3.22); // double 
	System.out.println('A'); // char
	System.out.println(true); // boolean
}

}

跨类调用静态方法, 必须使用类.方法
int c = MethodTest.add(a, b); // .表示隶属关系.
System.out.println©;

递归调用

方法调用时,调用方法本身,称为递归调用

递归调用代码实例练习:

public class SimpleTest {
   
	
/**
	求n的阶乘
	求 n * n-1的阶乘, 递归 : 把问题分解成一个小问题和一个子问题.
	递归是告诉计算机做什么, 而普通方法则是告诉计算机怎么做.
*/
public static int test(int n) {
   
	//test(n); // 方法调用自身, 这样的调用称为递归调用, 这样的递归会形成无限递归, 死归
	if (n <= 1) {
   
		return 1;
	}
	return n * test(n - 1);
}

public static void main(String[] args) {
   
	System.out.println(test(5));
}

}

家庭记账软件项目

public class FamilyAccount {
   
	public static void main(String[] args) {
   
		// 声明变量保存基本金, 初值是10000
		int balance = 10000;
		// 声明变量保存记账本, 初值是明细表的表头
		String details = "收支\t账户金额\t收支金额\t说    明\n";
		// 声明一个用于控制循环的布尔变量, 初值是true
		boolean loopFlag = true;
		// 写一个循环
		do {
   
			// 1) 打印主菜单
			System.out.println("-----------------家庭收支记账软件-----------------");
            System.out.println("");
            System.out.println("       1 收支明细");
            System.out.println("       2 登记收入");
            System.out.println("       3 登记支出");
            System.out.println("       4 退    出");
            System.out.println("");
            System.out.print("       请选择(1-4) : ");
			// 2) 通过调用工具类的方法Utility.readMenuSelection(), 获取用户输入的'1'~'4', 
			//	  此方法会返回一个char型的值, 声明变量接收这个char型值.
			char ch = Utility.readMenuSelection(); // 它会一直等待用户从键盘输入数字
			// 3) 对用户的输入作分支
			switch (ch) {
   
				// 4) 如果是'1', 打印记账本字符串
				case '1' :
					System.out.println(details);
					break;
				// 5) 如果是'2', 打印"处理收入"
				case '2' :
					//打印提醒 : 本次收入金额 : 
					System.out.print("本次收入金额 : "); 
					//真的调用工具方法获取用户从键盘的实际的输入的整数, 并用变量接收.
					int money1 = Utility.readNumber();
					//打印提醒 : 本次收入说明 :
					System.out.print("本次收入说明 : ");
					//真的调用工具方法获取用户从键盘的实际的输入的说明字符串, 并用变量接收.
					String string1 = Utility.readString();
					// 调整余额, 累加本次收入的金额
					balance += money1;
					// 拼接本次收入明细
					//String info1 = "收入" + 调整后的余额 + 本次收入的金额 + 本次收入说明字符串 + 换行
					String info1 = "收入" + "\t" + balance + "\t\t" + money1 + "\t\t" + string1 + "\n";
					// 最后把此次收入明细串, 拼接到details的后面
					details += info1;
					break;
				// 6) 如果是'3', 打印"处理支出"
				case '3' :
					//打印提醒 : 本次支出金额 : 
					System.out.print("本次支出金额 : "); 
					//真的调用工具方法获取用户从键盘的实际的输入的整数, 并用变量接收.
					int money2 = Utility.readNumber();
					//打印提醒 : 本次支出说明 :
					System.out.print("本次支出说明 : ");
					//真的调用工具方法获取用户从键盘的实际的输入的说明字符串, 并用变量接收.
					String string2 = Utility.readString();
					// 调整余额, 把支出的金额从余额中累减
					balance -= money2;
					// 拼接本次支出明细
					//String info2 = "支出" + 调整后的余额 + 本次支出的金额 + 本次支出说明字符串 + 换行
					String info2 = "支出" + "\t" + balance + "\t\t" + money2 + "\t\t" + string2 + "\n";
					// 最后把此次收入明细串, 拼接到details的后面
					details += info2;
					break;
				// 7) 如果是'4', 把控制循环的布尔置为false
				case '4' :
					System.out.print("确认是否退出(Y/N) : ");
					char confirm = Utility.readConfirmSelection();
					if (confirm == 'Y') {
   
						loopFlag = false;
					}
					break;
			}
		} while (loopFlag);
	}
	
}

面向对象编程

类与对象

类:一类具有相同特性的事物的抽象描述,例如:Student,Circle等

对象:这类事物的一个具体的个体,例如:其中一个学生对象

类是模板,设计图,理解为汽车设计图

对象是实体,理解为实际存在的汽车

面向对象的三大特征:

  1. 封装
  2. 继承
  3. 多态

面向对象 : 关注的是具有功能的对象

面向对象3条主线:

  1. 类及类的成员的学习
  2. 三大特性(封装, 继承, 多态)
  3. 其他关键字

面向对象编程中 : 目标是使用对象来完成功能, 如果对象没有现成的, 制造一个对象来使用.

面向对象程序重点 : 类的设计

类 : 描述复杂的现实世界某种事物, 是一个抽象的,是概念上的.
类就是和普通数据类型一样的数据类型, 只不过是一种复合类型. 类类型或称为引用类型

对象 : 类的某个具体的实体, 也称为实例.
重点 : 类的研究和设计. 类的成员 : 属性, 方法, 构造器

设计类 :
考虑事物的数据部分, 成员(member)变量(属性)来描述.
考虑事物的行为动作, 成员(member)方法来描述.

面向对象代码练习实例

创建类及类的成员

public class Teacher {
   	

// 特征 : 姓名, 年龄, 性别, 身高, 体重, 工资 .....
String name; // 对象属性, 隶属于某个对象, 也称为实例变量.
int age;
String gender;

// 行为 : 吃饭, 上课, 睡觉, 玩, 看电影, 做饭 ......
// 方法 : 修饰符, 返回值类型, 方法名(参数列表) {方法体}
// 对象方法, 隶属于某个对象. 注意点 : 方法千万不要加static修饰符!!!!! 
public void eat(String some) {
    // 吃什么取决于调用者传的参
	System.out.println("老师在吃" + some);
}

public void lesson() {
   
	System.out.println("老师在上课...");
}

// 自我介绍, 用一个字符串描述对象的详细信息, 详细信息就是对象的所有属性值拼接
public String say() {
   
	String str = "姓名 : " + name + ", 年龄 : " + age + ", 性别 : " + gender;
	return str;
}

}


创建类的对象

public class TeacherTest {
   	

public static void main(String[] args) {
   
	// 类已经就绪 , 模板就位, 使用模板制造对象
	Teacher t = new Teacher(); // 左侧的Teacher是对象的类型.
	
	/*
	int n = 200;
	n = 30;
	System.out.println(n);
	*/
	
	t.name = "佟刚";
	t.age = 40;
	t.gender = "男";
	
	System.out.println(t.name);
	System.out.println(t.age);
	System.out.println(t.gender);
	
	t.lesson();
	t.eat("面包");
	String s = t.say(); // 接收返回值
	System.out.println(s);
}

}

成员变量

(1)静态变量与实例变量的选择

  • 如果这个特征值是整个类的所有对象共享的,那么就声明为静态的;
    • 一个对象设置和修改了静态变量,这个类的所有对象都会受到影响
    • 所以,建议通过类来修改和访问,而不是通过对象
  • 如果这个特征值是每一个对象独立的,那么就声明为非静态的;
    • 一个对象设置和修改了和其他对象无关

(2)成员变量与局部变量的异同

相同点:
1、变量的三要素

数据类型、变量名、变量值

2、变量的使用要求

无论是成员变量还是局部变量都要先声明后使用,即我们只能使用声明过的变量,否则编译会报错

不同点:
1、作用域与可见性范围:
  • 局部变量有作用域:超出作用域就不能使用

  • 成员变量有可见性范围:只要可见就可以通过相应的方式直接操作

    • 在本类中,直接访问,但是静态的方法和代码块不能直接访问本类非静态的成员变量

    • 在其他类中:静态的建议通过**“类名.”**进行访问,虽然也可以通过“对象名."进行访问

      ​ 非静态的通过**“对象名."**进行访问

2、重名问题
  • 同一个作用域中局部变量不能重复声明
  • 同一个类中不能成员变量不能重复声明
  • 当局部变量与成员变量重名时,要注意区别
    • 静态变量:类名.静态变量
    • 实例变量:this.实例变量
3、初始化要求
  • 局部变量必须手动初始化
    • 方法体和代码块中必须有“变量 = 值"的语句,才能使用这个变量
    • 方法的形参必须在调用时传入实参为其赋值
  • 成员变量
    • 如果没有显式初始化,它有默认值
    • 也可以进行显式赋值
4、内存位置
  • 局部变量:方法调用时在方法对应的栈中
  • 成员变量:
    • 静态变量:在类对应的方法区中
    • 实例变量:在每一个对象的堆中
5、生命周期
  • 局部变量:只有该方法或代码块正在执行时,才会存在,执行完立刻消失
  • 成员变量:
    • 静态变量:只要这个类还在,就一直可以访问,即静态变量与类共存亡
    • 实例变量:只要这个对象还在,就可以访问到,即实例变量与对象共存亡,每一个对象的实例变量是独立的
6、修饰符
  • 局部变量:没有修饰符,除了final,如果加了final就表示值不能修改,就是常量了
  • 成员变量:可以有很多修饰符:public, protected, private ,static, final, transient, volatile等

成员方法

(1)什么是方法

方法(method),又称为函数(function),是指代表一段独立的可复用的功能。

换句话说,我们定义方法/抽取方法的目的是使得某个功能可以被重复使用。

例如:

System.out.println(xx); 这里调用了out对象的println方法,用来输出xx并换行。

Math.sqrt(x):这里调用了Math类的sqrt方法,用来获取x的平方根。

Scanner对象的nextInt():调用Scanner对象的 nextInt(),用来从键盘接收一个整数值

(2)方法的特点和要求

  • 方法是必须先声明后使用
  • 方法不调用不执行,调用一次执行一次

(3)声明格式

必须在类中,方法外声明

【修饰符】 返回值类型  方法名(【形参列表】){
   
	方法体
}

关于【修饰符】有很多:public, protected, private,static,abstract,final,native,synchronized等等,一个个慢慢学。

(4)分类

  • 静态方法:有static修饰的
    • 本类中直接调用
    • 其他类中,静态的建议通过**“类名.”**进行访问,虽然也可以通过“对象名."进行访问
  • 非静态方法:没有static修饰的
    • 本类中,只能在本类的非静态方法和代码块中直接调用,同样静态的方法和代码块不能直接访问本类非静态的成员方法
    • 其他类中,非静态方法通过**“对象名."**进行访问

(5)参数传递机制:形参与实参

  1. 方法的参数:方法名后面()里面的东西,就是方法的参数
  2. 为什么有方法的参数?方法的参数是做什么用的?
    方法是代表一个独立的可复用的功能。
    那么我们的方法体,就是实现功能的代码。
    当我们在实现这个功能的时候,需要一些额外的数据。
    例如:设计一个求两个整数和的功能,那么我们就需要两个整数
    如何得到这两个整数?
    A:在方法体里面从键盘输入
    B:让调用者传入这两个整数,至于这两个整数从哪里来,由调用者自己决定
    结论:方法的参数是用来接收数据的,调用者给它的数据,用于辅助完成方法的功能
  3. 参数分为形参和实参
    形参:方法声明的()中的是形参,因为在被调用之前,他没有值,只是个形式
    int sum3(int a, int b) 没有调用之前,(int a, int b) 是没有值的,是个形式,但是要说明数据类型,
    准备接受什么值。
  • 实参:方法调用的()中的是实参,因为在调用时,它就有具体的值了。
    sum3(1,2) 其中1,2是实参
    sum3(i,j) 其中i,j是实参
    d.sum3(d.sum3(i,j) ,k); 对于d.sum3(i,j)部分,i和j是实参,
    d.sum3(d.sum3(i,j) ,k)部分,第一次调用d.sum3(i,j)的结果是实参之一,k是实参之二
  • 实参:给形参赋值的

(6)返回值与return

看方法完成的功能,是否需要调用接收结果。

如果不需要返回结果,那么返回值类型处就写void,在方法体中,如果要提前结束方法,可以使用return;

如果需要返回结果,那么返回值类型处就不能写void,写具体的类型,在方法体中,必须有return 返回值;

(7)方法的参数传递机制

方法的参数传递机制
即实参给形参传了什么值?互相之间的关系是什么样?
(1)实参给形参赋值
(2)实参给形参什么值?
基本数据类型,数据值
引用数据类型,地址值
(3)实参是否会被形参影响
基本数据类型,形参无论怎么修改和实参无关,因为是实参是复制了一份数据给形参。
引用数据类型,形参对象修改了属性/形参数组对象修改了元素,实参会跟着变,因为实参把对象的地址值给形参了,
那么形参和实参就是指向同一个对象。

陷阱:
当形参指向了新对象之后,接下来的操作就和实参无关了

(8)重载

定义:在一个类中出现了,两个或更多个,方法名称相同,形参列表不同的方法就是重载。和返回值类型、权限修饰符无关。

(9)main方法的命令行参数

public class TestCommandParam {
   
	//main方法的(String[] args)形参怎么传实参
	//java 类名  参数值1  参数值2  参数值3
	public static void main(String[] args) {
   
		for (int i = 0; i < args.length; i++) {
   
			System.out.println(args[i]);
		}
	}
}



(10)方法调用的入栈与出栈

每一次方法调用都会在栈中开辟一块独立的空间,用来存储这个方法的局部变量等信息,所以每一次局部变量的值都是全新的。称为“入栈”

每一次方法调用结束之后,都会释放栈空间。称为“出栈”

构造器

构造器也称为构造方法,

本质上是一个方法. 作用 : 在对象创建时进行初始化工作的

构造器的特殊性 :

​ 1) 构造方法名和类名一致, 这是唯一允许使用首字母大写的方法名的方法
​ 2) 它不声明返回值类型, 甚至连void也没有
​ 3) 它不可以被一些关键字修饰, static ,final, abstract…
​ 4) 它不能像普通方法一样随意调用. 只能在创建对象时执行仅有的一次

如果我们在类中并未提供任何构造器, 编译器会自动添加一个缺省构造器 : 无参, 修饰符和类一致, 方法中没有语句.
如果我们在类中提供了构造器, 编译器就不会再自动添加一个缺省构造器了
结论 : 所有类都必须有构造器

构造器重载 : 多个构造器只要参数不同就可以重载

构造器的要求

  • 每一个类都有构造器
    • 如果一个类没有手动编写构造器,编译器就会自动生成一个无参构造器
    • 如果一个类手动编写了构造器,那么编译器就不会自动给你加无参构造器了,如果需要可以自己写
  • 构造器的名称必须和类名相同
  • 构造器没有返回值类型(包括void)
  • 构造器可以重载

构造器的作用和调用

  • 构造器的作用是在创建对象时为成员变量初始化用的。
  • 我们创建对象时,new后面就是构造器。创建哪个类的对象,就调用哪个类的构造器。
new 类名()  表示调用无参构造创建对象
new 类名(实参)  表示调用有参构造创建对象

示例代码

1、没有编写构造器

示例代码:

class ClassA{
   
	
}
public class TestConstructor {
   
	public static void main(String[] args) {
   
		ClassA a = new ClassA();
		//调用无参构造,这个无参构造是编译器自动增加的
	}
}
2、只编写了有参构造

示例代码:

class ClassB{
   
	private int b;

	public ClassB(int b) {
   
		this.b = b;
	}	
}
public class TestConstructor {
   
	public static void main(String[] args) {
   
		
//		ClassB b1 = new ClassB();
		//报错,编译器不会自动增加无参构造,因为你自己写了有参构造
		
		ClassB b2 = new ClassB(5);//调用有参构造创建对象
	}
}
3、既有有参构造又有无参构造

示例代码:

class ClassC{
   
	private int num;

	public ClassC(int num) {
   
		this.num = num;
	}

	public ClassC() {
   

	}
	
}
public class TestConstructor {
   
	public static void main(String[] args) {
   
		
		ClassC c1 = new ClassC();//调用无参构造
		ClassC c2 = new ClassC(6);//调用有参构造
	}
}

4、构造器如果写返回值类型,就不是构造器了
class ClassD{
   
	//不是构造器
	public void ClassD(){
   
		System.out.println("普通方法");
	}
}
public class TestConstructor {
   
	public static void main(String[] args) {
   
	
		ClassD d1 = new ClassD();
		//调用无参构造
		//调用编译器自动生成的无参构造
		
		d1.ClassD();//调用普通方法
	}
}

构造器的权限修饰符

(1)当一个类没有编写构造器,编译器会自动产生一个无参构造。这个无参构造的权限修饰符和类一致。

下面的两个类:

  • TestConstructor2的无参构造,权限修饰符是public的。
  • Demo的无参构造,权限修饰符是缺省的。
public class TestConstructor2 {
   

}
class Demo{
   
	
}


(2)怎么定它的权限修饰符是什么?

看你希望它在哪个范围内能够创建对象

  • 如果你只希望这个类在本类中创建对象,即类的外面不能创建对象,那么就是private,例如:单例,枚举等类型
  • 如果你只希望这个类在本包中创建对象,出了这个包就不能随意创建对象,那么就是缺省的

如何选择有参构造和无参构造

  • 无参构造,创建对象简单,直接new 类名()就可以。特别是后面通过反射或框架帮我们创建对象,那么无参构造都是最最有用的。而且在子类继承时,无参构造也很有用。如果没有极特殊的情况,一个类都要保留它的无参构造。
  • 有参构造,如果你在new对象时,就能够为成员变量提供初始值,那么选择有参构造呢,会更方便。
  • 你声明的构造器的形式越多,那么代表自己或其他人来创建这个类的对象的方式就越多,就更灵活方便。

对象关联

对象关联 : 一个类的对象关联另外一个类的对象, 一个对象拥有另外一个对象

为什么要关联 : 在当前类中要频繁地使用另外一个类的对象

如何关联 : 在当前类中把另外一个类的对象作为我的属性即可.

属性该如何处理 :

    1. 修改全参构造
    1. 提供get/set方法
    1. 修改say方法

一旦作为属性, 就是成员, 成员意味着大家随便用!!!

代码实例练习(一):

public class Teacher {
   

private String name;
private int age;
private String gender;
private Computer myComputer; // 对象关联, 被关联的对象

public Teacher() {
   }

public Teacher(String name, int age, String gender, Computer myComputer) {
   
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.myComputer = myComputer;
}

public void setMyComputer(Computer myComputer) {
   
    this.myComputer = myComputer;
}

public Computer getMyComputer() {
   
    return myComputer;
}

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

public String getName() {
   
    return name;
}

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

public int getAge() {
   
    return age;
}

public void setGender(String gender) {
   
    this.gender = gender;
}

public String getGender() {
   
    return gender;
}

public String say() {
   
    return "姓名 : " + name + ", 年龄 : " + age + ", 性别 : " + gender + ", 我的电脑 : " + myComputer.say();
}

//public void lesson(Computer com) {
   
public void lesson() {
   
    System.out.println(name + "老师在使用电脑[" + myComputer.say() + "]上课");
}

public void film() {
   
    System.out.println("老师在使用电脑[" + myComputer.say() + "]在看电影");
}
}

对象双向关联实例一

我们让一个Boy对象关联一个Girl对象,同时,让这个Girl对象也关联这个Boy对象,有点像“你中有我,我中有你”的关系。

public class 
在《Java学习笔记》,可以找到有关JavaSE基本知识的内容。其可能包括Java的基本语法、数据类型、控制流程、面向对象编程等方面的知识。如果您想要打印JavaSE知识的内容,可以使用Java的IO流来实现。您可以使用System.out.println或者其他打印方法来在控制台输出您想要的JavaSE知识。根据您提供的代码片段,在MapText类的main方法使用了System.out.println来打印存储在Map的值,实现了对键值对的打印输出。另外,您还提供了一个匿名内部类的示例,其重写了MyInterface接口的add方法,通过System.out.println打印了"-------add------"的内容。根据您的需求,您可以根据具体的知识点和代码实现,在适当的位置使用System.out.println或其他打印方法来打印出您想要的JavaSE知识内容。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [[Java学习笔记doc]-javase基本知识](https://download.csdn.net/download/arthas777/88206261)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [JavaSE知识点整理](https://blog.csdn.net/Kxxindy/article/details/123136578)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值