JavaSE 基础
第一章 计算机基础知识
1.1 计算机发展趋势和二进制以及语言发展史
1.1.1 计算机的发展趋势
- 微型化
- 巨型化
- 智能化
1.1.2 二进制
- 计算机只能识别 0 和 1,所以在进行存储时,都是通过二进制来进行存储的
- 0 和 1 简单,所以可以代表电的低频和高频
- 也可以进行一些逻辑运算
- 还可以通过逻辑门电路来实现一些运算
1.1.3 语言发展史
-
机器语言
-
汇编语言
-
高级语言
1.2 Java 发展史 、Java体系、Java 平台
1.2.1 Java 发展史
- Java 源自于 sun 公司,创始人是 高司令,起源于 green 项目
- 2009 年 sun 被 Oracle 收购
- 没被收购之前,每两年更新一次
- 收购之后,每半年更新一次
- 目前稳定版:jdk8、jdk11
1.2.2 Java 体系
1.2.3 Java 平台
-
JavaSE(基础版)
-
JavaEE(面向企业级应用桌面程序开发)
-
JavaME(嵌入式开发)
1.3 Java 如何实现跨平台的
1.4 开发软件
- 高级文本编辑器:Notepad++
- 开发软件:IDEA
1.5 常用的 DOS 命令
-
命令的几种形式?
- 内部命令(操作系统内置)
- 外部命令(通过安装第三方软件,需要进行一些配置)
- 批处理文件(bat)
-
命令的使用方式
- help 命令
- 命令 [属性] [路劲]
-
常用的命令
- cd (进入指定的目录结构)
- cd …(返回上一级)
- cd /(返回根目录)
- dir(查看当前目录,有哪些文件和目录)
1.6 JDK 的安装与配置
- JDK 官网
- 软件安装,双击运行,一直下一步
1.7 书写第一个HelloWorld
1.7.1 代码示例
public class HelloWorld {
public static void main(String[] args) {
System.out.prinlnt("HelloWorld");
}
}
1.7.2 DOS 命令编译执行 Java 源文件
- javac(用来将 Java 源文件,编译成 .class 文件)
- java(执行 Java.class 文件)
- java 命令后面,不能直接跟路劲,需要加上 -classpath 属性
- java -classpath 路劲 类名
- 点击:gif 图片演示
1.7.3 命令的执行步骤
-
命令在执行时,先会在当前所属目录去查找
-
当前所属目录没有,就会去环境变量里面去找
-
环境变量
-
用户变量(只对当前用户生效)
-
系统变量(对整个系统生效)
-
先去用户变量中查找,没有找到,再去系统变量中找,找到就执行
-
没有找到,如下图
-
1.8 Java 环境变量配置
-
为什么需要配置环境变量?
- 如果不进行配置,DOS 执行对应的命令时,需要去对应命令所属的目录里面去执行
- 而且命令所执行的文件(目标),跟命令不在同一位置
- 配置完,环境变量后,就可以在任意目录使用命令
-
为什么需要配置 JAVA_HOME?
- JAVA_HOME 这个名字本身,是可以随便起的
- 但是由于大不部分人,都用 JAVA_HOME 这个名字
- 所以就导致有些软件需要用到 Java 环境,但是在查找 Java 环境时,是通过 JAVA_HOME 去查找的,如果没有找到就会报错!!
- 不容易错删,方便我们切换版本
-
为什么需要配置 path?
- path 里面包含了 windows 环境变量 中 可执行文件的绝对路径
- 由于 JDK 我们可能要安装多个版本,但是 JDK 版本的目录不同,所以遵循 “变化导入,不变保留”
- JAVA_HOME 里面定义 JDK 的目录
- path 里面引入 JAVA_HOME ,并拼接对应的 bin 目录
-
为什么不配置 CLASSPATH
- 在 JDK 1.5 之前,Java 命令无法完成 .class 文件的执行,需要通过 CLASSPATH 配置一些内容,来完成类的执行
- JDK 1.5 之后,就不需要配置 CLASSPATH 了
第二章 Java 的基础知识
2.1 Java 程序的常见错误
-
类名必须和文件名保持一致
-
严格区分大小写
-
单词拼错
-
{ } 缺失
-
标点符号是中文的
2.2 HelloWorld 程序解析
-
public class HelloWorld { public static void main(String[] args) { System.out.println("HelloWorld"); } }
-
public (公共的)
- 在一个 Java 源文件中,public 只能有一个
-
class (类)
- 在一个 Java 源文件中,class 可以有多个,在编译的过程中,会将这些 class 分别编译成 class 文件
- class 类想要执行必须包含 main 方法
-
HelloWorld (类名)
- 类名和文件名必须保持一致
- 大小写分明
-
public static void main(String[] agrs) {} (main 方法,程序的执行入口)
- static 静态的
- void 空的
- main (方法名)
- [](数组)
-
System.out.println()
(打印输入内容)-
System(系统)
-
out(输出)
-
println(打印换行)
-
print(打印)
-
() 需要打印的内容
-
2.3 注释
-
用于描述代码,方便别人进行查看和维护
-
/** 文档注释 用于声明类的信息,和帮助文档 */ public class Test { /* 多行注释 main 方法 程序执行的入口 */ public static void main(String[] args) { // 单行注释 System.out.println("注释"); } }
-
单行注释和多行注释,只在编码环境中生效
-
文档注释的生命周期在,编译环境
2.4 标识符
- 不能以数字开头
- 首字母可以用 26个英文字母 或 下划线 或者 $ 开头,后面可以跟字母、下划线、$ 和 数字
- 标识符不可以是关键字
- 严格区分字母大小写
- 驼峰命令法
- 大驼峰
- 单个单词,首字母大写
- 多个单词,每个单词的首字母大写,其余字母小写
- 类、接口、注解
- 小驼峰
- 单个单词,全部小写
- 多个单词,从第二个单词开始,每个单词的首字母大写,其余字母小写
- 变量、方法
- 大驼峰
2.5 关键字
-
在 Java 中,已经规定了其用法的单词,这些单词不能作为标识符,关键字又称为保留字。
-
常用的关键字
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sihkcd9Y-1638851240009)(…/…/image/JavaSE/01_计算机基本知识/关键字.jpg)]
2.6 字符集合
- 字符集合是指一个国家的所以文字和字符的集合
- 不同国家的字符各有差异
- 计算机是老外发明的,底层是用 ASCII 表来字符进行存储的
- 输入一个字符,就会去对应的字符表中去找当前字符对应的数字
- 当一个国家的文字出现,另一个国家的字符表中,那么就会乱码
- 解决方案
- 修改文件编码的格式或修改解码文件的格式
- 文件编码和解码格式必须做到统一
javac -encoding utf-8 文件名
2.5 变量
-
内存地址的引用,在生命周期期间可以重复引用
-
变量的语法
- 数据类型 变量名 = 值;
-
变量的三要素
- 数据类型、变量名、作用域(生命周期 作用范围)
-
图解
-
public class Test { public static void main(String[] args) { /* * 变量的声明方式? * 先声明后初始化 * 声明并初始化 * 在 Java 中,变量必须先初始化,才能被引用,否则就会报错 */ int num; num = 20; System.out.println(num); num = 30; System.out.println(num); int num2 = 30; } }
2.6 常量
- 通过 final 进行修饰,一旦赋值就不可
第三章 数据类型与运算符以及流程控制语句
3.1 数据类型分类
- 基本数据类型
- 整数类型
- byte (字节型)、short(短整型)、int(整形)、long(长整型)
- 浮点型
- float(单精度浮点型)、double(双精度浮点型)
- 字符型
- char
- 布尔型
- boolean
- 整数类型
- 引用数据
3.2 数据类型介绍
数据类型 | 范围 |
---|---|
byte | 1个字节 -27~27-1 [-128~127] |
short | 2个字节 -215~215-1 [-32768~32767] |
int | 4个字节 -231~231-1 [-2147483648~2147483647] 约21亿 |
long | 8 个字节 -263~263 -1 |
float | 4 个字节 精确到小数点为7 |
double | 8 个字节 是 float 的两倍 |
char | 2 字节 0~65535 |
boolean | 1 个字节 |
3.2.1 整数类型
-
public class Test { public static void main(String[] args) { //byte byte num = 127; //错误:从 int 转 byte 会造成精度丢失,不兼容 //num = 128; System.out.println(num); //short short num2 = 32767; //错误:从 int 转 short 会造成精度丢失,不兼容 //num2 = 32768; //int int num3 = 2147483647; //错误:过大的整数 //num3 = 2147483648; System.out.println(num3); //long long num4 = 2147483647; num4 = 2147483648L; System.out.println(num4); } }
-
注意:
- 在 Java 中所有整数类型的字面值是 int 类型, 在给数据类型赋值时,不超过对应类型赋值范围,那么这个值,就是对应的数据类型
- 一旦超过,这个值就会真正的变成 int 类型,int 赋值 比他小的数据类型,会导致精度丢失,不兼容
- 在值的后面加上 L 表示 long 类型
-
赋值方式
public class Test { public static void main(String[] args) { // 二进制 0b 开头 int num = 0b101010; // 八进制 0 开头 int num2 = 01234567; // 十进制 正常写 int num3 = 1025; // 十六进制 0x 开头 int num4 = 0x125EA; } }
3.2.2 浮点数
-
public class Test { public static void main(String[] args) { //有效小数点 7 位 float num = 2.12547858f; System.out.println(num); //double 能够精确到小数点 15 位 double num2 = 2.1111111111111189 ; System.out.println(num2); //计算机是用二进制来存储数据,所以有些小数不能精确的表示 double num3 = 0.1; double num4 = 0.1; System.out.println(num3 == num4); // true num4 = 1/10; System.out.println(num3 == num4); // false } }
-
注意
- 在 Java 中所有浮点型默认值是 double 类型,所以在给 float 赋值时,后面需要加上 f 或 F
- double 类型的值,可以在后面加上 d 或 D
- 由于浮点数能够精确表示的小数有限,有些小数不能精确的表示,所以浮点数不适合做四则运算
- 想要做科学运算,可以使用
BigDecimal
-
赋值方式
public class Test { public static void main(String[] args) { // 小数的整数如果是0,那么0可以省略 double num = .5; // 科学计数法 314.0 0.314 double num2 = 3.14E2; double num3 = 3.14E-1; } }
3.2.3 字符型
-
由于 Java 是采用 Unicode 进行编码的,Unicode 每位字符的存储是2个字节,所以它范围是 0~65535 之间也可以使用 Unicode 的形式进行赋值
-
char 类型为什么可以赋值数字,首先计算机是通过 ASCII 表进行存储的,同时 Unicode 兼容 ASCII 表
-
public class Test { public static void main(String[] args) { //char 通过 '' 来进行赋值 char str = 'A'; System.out.println(str); System.out.println(str + 10); //通过数字来赋值 str = 97; System.out.println(str); System.out.println(str + 10); //通过 Unicode 进行赋值 str = '\u0000'; System.out.println(str); } }
-
注意事项
- ‘’ 表示的是字符,"" 表示的是字符串,它们两个不一样
3.2.4 布尔型
-
boolean 是布尔类型,它的值是 true 和 false,通过 true 和 false 又代表 1 和 0
-
public class Test { public static void main(String[] args) { boolean flag = true; flag = 20>25; System.out.println(flag); } }
-
注意事项
在 <<Java 虚拟机规范>> 一书中写道,虽然定义了 boolean,但是却没有指定其范围,所以 boolean 类型在被编译时,
默认是当做 int 类型来处理的,但如果是 数组 类型,那么就会被当做 byte[] 来处理
3.3 数据类型转换
3.3.1 隐式类型转换
- 实线箭头表示转换不会丢失精度,虚线箭头表示转换会损失精度
- 隐式转换就是由小向大转换,不会造成精度丢失
3.3.2 强制类型转换
-
由大向小转换,会造成精度丢失
-
public class Test { public static void main(String[] args) { // int 转 byte int num = 20; byte num2 = (byte)num; // long 转 int long num3 = 20L; int num4 = (int)num3; //四则运算 int num5 = (int)(20*5+25L/3.0d); } }
-
在进行四则运算中,最终结果以数据类型最大的那个为主,但是可能这个值的数据类型和变量的数据类型,不匹配需要强转
3.4 转义字符
-
将特殊含义的字符,转换成普通字符串
-
\t \n \r \
-
一般就是用 \t 和 \n 其他的看看就好,不重要!!
-
public class Test { public static void main(String[] args) { /* * \n 换行,将光标移动到下一行首行 * \r 将光标,移动到当前行的首行 * 如 \r 前后都有内容,那么后面的内容就会替换前面的所有内容 * * \t 空格 8 位,如果 \t 前面有字符串,那么就会根据字符串的个数和8对减,从而得出 * 打印多少个空格,如果前面的字符串个数是8个,那么 \t 就会打印 8 个空格 * 如果 \t 前面没有内容,会打印 8 个空格, \t 前面的内容不仅可以是字符串 * \ 将有特殊含义的字符,转换成普通的字符串 */ System.out.println("sdssdf" + "\n" + "sdfsd"); System.out.println("11111" + "\r" + "a"); System.out.println('a'+'b'+"\t" + "1"); System.out.println("\t" + "1"); System.out.println("\\"); System.out.println("\""); } }
3.5 运算符
3.5.1 什么是表达式?
3.5.2 算数运算符
-
+ - * / % ++ --
-
public class Test { public static void main(String[] args) { //+ - * / % ++ -- int num = 10; System.out.println(num + 10); System.out.println(num - 10); System.out.println(num * 20); System.out.println(num / 5); // % 取模 除于这个数,并取余 System.out.println(num % 5); //在四则运算中,有多个数据类型,进行运算,最终结果的数据类型,以最大的那个为主 //注意:因为操作数是两两进行运算的,在没有碰到那个最大的数据类型之前,操作数的类型都是默认类型 double num2 = 20/8; System.out.println(num2); num2 = 20d/25*9L; num2 = ((double) 30)/65*23.6f+25L; System.out.println(num2); /* * + 既可以做加法运算也可以做字符串拼接符号 * 当表达式中,既有加法运算也有字符串拼接,此时则不在进行运算 * 除非表达式中,还有其他运算,那么就会先进行除加法之外的运算符运算,在进行拼接 */ //1HelloWorld026 System.out.println(1+"HellWorld"+1/2+2+2*3); // ++ 自增 // ++ 在操作数后面的,被称为后自增,后自9.ui增是先运算在+1 int num3 = 10; int num4 = num3++; System.out.println(num4); System.out.println(num3); // ++ 在操作数前面被称为,前自增,前自增先+1后运算 num4 = ++num3; System.out.println(num4); System.out.println(num3); num3++; System.out.println(num3); // -- 自减 // -- 在操作数后面,被称为后自减,后自减是先运算在-1 int num5 = 20; int num6 = num5--; System.out.println(num6); System.out.println(num5); // -- 在操作数前面,被称为前自减,前自减是先-1在运算 num6 = --num5; System.out.println(num6); System.out.println(num5); //当 ++ 和 -- 写成独立的一条语句时,那么最终结果一定是自增或自减 --num5; System.out.println(num5); } }
-
注意事项:
- ++ 和 – 要注意在操作数前面和后面的区别
- ++ 和 – ,可以单独写成一条语句,那最终的结果一定是自增或自减
+
既可以做加法运算,也可以做字符串拼接
2.5.3 赋值运算符
- 在 Java 中
=
是赋值运算符,==
是等于运算符
3.5.4 关系运算符
-
> >= < <= == != instanceof
-
public class Test { public static void main(String[] args) { // > >= < <= == != instanceof //关系运算符最终的运算结果一定是 布尔值 System.out.println(20 > 5); System.out.println(20 < 5); System.out.println(20 >= 20); System.out.println(5 <= 30); System.out.println(1 == 2); System.out.println(2 != 1); } }
-
注意
- != 和 == 即可以判断基本数据类型也可以判断引用类型
- instanceof 只能判断引用数据类型
> >= < <=
只能判断基本数据类型- = 和 == 的区别
3.5.5 扩展运算符
-
+= -= /= *=
-
public class Test { public static void main(String[] args) { // += -= *= /= int num = 20; //num = num + (10 + 2) num += 10 + 2; // num = num - 20; num -= 20; // num = num * (20/5) num *= 20/5; // num = num / (2*3) num /= 2*3; // 可以进行隐式转换 num *= 20L+3; num += 23.6f+1; System.out.println(num); } }
-
扩展运算符的优缺点
- 扩展运算符可以进行隐式转换
- 优点
- 提高开发效率和编译效率
- 缺点
- 可读性变差了
3.5.6 逻辑运算符
-
& && | || ! ^
-
public class Test { public static void main(String[] args) { // && || ! ^ // && 两个表达式的条件为true,结果为true,否则为 false System.out.println((20 < 15) && (30 > 32)); // || 两个表达式其中一个为 true,则结果为 true,否则为 false System.out.println((10 > 20) || (25 < 10)); // ! 取反 System.out.println(!(10 == 2)); //相同为 false,不同为 true System.out.println((10 > 2) ^ (10 < 2)); } }
-
注意事项
- & 和 && 的区别
- & 左边表达式为 false,右边表达式也计算
- && 左边表达式为 false,右边则不在计算
- | 和 || 的区别
- | 左边表达式为 true,右边还要计算
- || 左边表达式为 true,右边则不在计算
- & 和 && 的区别
3.5.7 三目运算符
-
表达式1?表达式2:表达式3
-
如果表达式1的值为 true,那么就执行表达式2,如果为 false,则执行表达式3
-
public class Test { public static void main(String[] args) { //三元运算符 int num = 20; int num2 = 30; System.out.println(num>num2?"num大于num2":"num小于num2"); //计算三个数的最大值 int num3 = 15; int max = num>num2?(num2>num3?num2:num3):(num2<num3?num3:num2); System.out.println(max); } }
3.5.8 位运算
-
& | ~ ^ << >> >>>
-
public class Test { public static void main(String[] args) { // & | ~ >> >> >>> //相同为true,不同为 false //101 // 10 //000 System.out.println(5&2); //只要有一个为1,那么就是 1 //1010 // 101 //1111 System.out.println(10|5); //相同为 false,不同为 true //1010 // 101 //1111 System.out.println(10^5); //取反 //00101 //11010 补码,负数在计算机中是用补码来进行存储和计算的,所以这个数取反之后,就变成了补码 //11001 尾数减 1 变成 补码 //10110 符号位不变,其余数字按位取反,变成原码 System.out.println(~5); //左移2位 -5*2^2,左移不管是正数还是负数后面都是补0 System.out.println(-5<<2); //左移2位 5*2^2 System.out.println(5<<2); //右移2位,10/2^2 System.out.println(10>>10); //右移2位,-10/2^2,右移正数前面补0,负数前面补1 System.out.println(-10>>2); // >>> 如果是正数按照 >> 来计算 System.out.println(-10>>>8); } }
-
扩展
-
& 可以判断一个数基偶性
-
基数尾数一定是1
-
System.out.println(5&1); // 1 System.out.println(4&1); // 0
-
-
^ 可以交换两个数的位置
-
public class Test { public static void main(String[] args) { int a = 5; int b = 2; //n^n^m = m a = a ^ b; // 101^10 = 111 7 b = a ^ b; // 111 ^ 10 = 101 5 a = b ^ a; // 111 ^ 101 = 10 2 System.out.println(a); System.out.println(b); } }
-
-
3.5.9 运算符的优先级
- 单目》双目》多目
- 想要控制运算符的顺序,请使用小括号!!!
- 不要试图使用运算符的优先级来控制运算顺序!!!
3.6 流程控制语句
3.6.1 选择控制语句
3.6.1.1 if 语句
表达式中的结果只能是布尔类型
if 单分支
语法
// 如果表达式为true,则执行逻辑代码
if (表达式) {
逻辑代码
}
示例
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//键盘录入
Scanner sc = new Scanner(System.in);
System.out.println("请输入数字");
//获取输入的内容
int num = sc.nextInt();
//if 判断数字是否大于等于 50
if (num >= 50) {
System.out.println("当前数字大于等于50");
}
}
}
多分支
语法
// 如果表达式的值为 true,则执行逻辑代码1,否则就执行逻辑代码2
if (表达式) {
逻辑代码1
}else {
逻辑代码2
}
示例
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//键盘录入
Scanner sc = new Scanner(System.in);
System.out.println("请输入数字");
//获取输入的内容
int num = sc.nextInt();
//if 判断数字是否大于等于 50
if (num >= 50) {
System.out.println("当前数字大于等于50");
}else {
System.out.println("当前数字小于50");
}
}
}
多分支
语法
// 程序会依次判断表达式中的值是否对等,如果对等就执行相应的逻辑代码,如果最终都没选中,则执行 else
// 如表达式1不等,就判断表达式2,表达式2不等,就判断表达式3,表达式3相等则执行对应的逻辑代码,其他都不执行
if (表达式1) {
逻辑代码1
}else if (表达式2) {
逻辑代码2
}else if (表达式3) {
逻辑代码3
}else {
逻辑代码4
}
示例
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//键盘录入
Scanner sc = new Scanner(System.in);
System.out.println("请输入数字");
//获取输入的内容
int num = sc.nextInt();
// 输入学生的成绩判断,属于哪个水平
if (num > 10 && num <= 20) {
System.out.println("男女混合双打");
}else if (num > 20 && num <= 30) {
System.out.println("男子单打");
}else if (num > 30 && num <= 40) {
System.out.println("女子单打");
}else if (num > 40 && num <= 50) {
System.out.println("骚年继续努力");
}else if (num > 50 && num <= 60) {
System.out.println("不及格");
}else if (num > 60 && num <= 70) {
System.out.println("勉强及格");
}else if (num > 70 && num <= 80) {
System.out.println("一般");
}else if (num > 80 &&num <= 90) {
System.out.println("优秀");
}else if (num > 90 && num <= 100) {
System.out.println("顶尖");
}else {
System.out.println("退学!!!!!");
}
}
}
注意事项
- if 多分支最好不要超过3个,不含 else
- 尽量简化 if 分支,多变双,双边单
- 逻辑代码最好不要写在 if 里面,建议写在外面,推荐报错写在 if 里面,根据情况来定
3.6.1.2 switch 语句
语法
// 判断表达式的值,是否与 case 的值相等,如果相等则执行对应 case 的语句里面的代码,如果最终都未选中则执行 default
switch(表达式) {
case 值1:
执行代码1
case 值2:
执行代码2
case 值3:
执行代码3
.....
default:
}
示例
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//键盘录入
Scanner sc = new Scanner(System.in);
System.out.println("请输入名称");
//获取输入的内容
String name = sc.nextLine();
//根据名称,返回对应的专业信息
switch (name) {
case "小丁":
System.out.println("计算机");
//break 跳出 switch 语句
break;
case "小明":
System.out.println("电子商务");
break;
case "小红":
System.out.println("直播带货");
break;
case "小兰":
System.out.println("土木工程");
break;
default:
System.out.println("未选择专业");
break;
}
}
}
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//键盘录入
Scanner sc = new Scanner(System.in);
System.out.println("请输入月份");
int num = sc.nextInt();
//根据月份判断季节
switch(num) {
case 11:
case 12:
case 1:
System.out.println("冬季");
break;
case 2:
case 3:
case 4:
System.out.println("春季");
break;
case 5:
case 6:
case 7:
System.out.println("夏季");
break;
case 8:
case 9:
case 10:
System.out.println("秋季");
break;
default:
System.out.println("请输入正确的季节!!!");
break;
}
}
}
注意事项
- 从 jdk1.5 开始之后,支持枚举,1.7 支持 String
- 除了long、boolean、float、double,其他基本数据类型均可使用
- 注意 switch 穿透,当前对应的 case 对等时,则执行 case 里面对应的语句,此时 case 里面没写 break 语句的话,那么程序就会一次往下执行,无视 case 条件,知道碰到 break 为止,如果最终没有碰到 break ,那么程序就会执行到末尾,包括 default
- 在 switch 中 default 顺序乱放(避免 switch 穿透的情况下),不会影响程序的执行
- int、byte、short、int 和 char 一样,char 三种赋值方式,均可在 switch 中执行,对应的整数类型也行
- if 常用与区间对比,switch 用于固定值判断
3.6.2 循环控制语句
3.6.2.1 while 循环
语法
while(表达式) {
执行内容
}
示例
public class Test {
public static void main(String[] args) {
//计算1~100的累加和
//定义初始化变量
int num = 1;
//存储累加和
int sum = 0;
//如果 num <= 100,则循环就会一直执行,知道 num 值 大于 100,则跳出循环
while (num<=100) {
//sum = sum + num;
sum += num;
//每循环一次,num的值就 +1,表达式条件的变更
//如果表达式的值,一直不变,那么就会变成死循环
num++;
}
//输出 sum 的值
System.out.println(sum);
}
}
执行顺序
- 先判断
- 如果条件为 true ,则执行一次,在判断在执行
- 直到条件为 false,则循环结束,执行后续代码
注意事项
- 先判断在执行
- 循环的三要素(初始化变量、表达式、表达式条件变更)
- while 适合,知道判断条件,却不知道执行次数场景使用
3.6.2.2 do while 循环
语法
//do while 循环是先执行在判断
do {
执行代码
}while(表达式);
示例
public class Test {
public static void main(String[] args) {
//定义一个随机数,如果随机数的值是<=99,那么就一直执行,直到这个随机数>99
//存储随机数
int num = 0;
//先执行,后判断
do {
//获取随机数
num = (int)(Math.random()*100+1);
//打印随机数
System.out.println(num);
}while (num <= 99);//条件判断
}
}
执行顺序
- 先执行,判断条件是否为 true,为 true 则继续执行,在判断
- 当条件为 false,则终止循环,执行后续代码
注意事项
- do while 和 while 的区别是:do while 是先执行在判断,while 是先判断在执行
- do while 适合,根据一个值,来判断是否继续要执行,比如说 腾讯QQ登录
3.6.2.3 for 循环
语法
for (;;) {
执行内容
}
示例
public class Test {
public static void main(String[] args) {
//循环打印10遍 HelloWorld
//i 初始值,i<10 是判断条件,i++ 条件变更
//我们发现 for 其实跟 while 很像,for 只是将三要素定义到了括号了
for (int i = 0;i<10;i++) {
System.out.println("HelloWorld");
}
/*
* 死循环
* 1、有初始值,判断条件,无条件变更
* 2、有初始值,无判断条件
* 3、三个都不写
*/
// for (int j = 0;j<10;) {
// System.out.println("有初始值,判断条件,无条件变更");
// }
// for (int k = 0;;k++) {
// System.out.println("有初始值,无判断条件");
// }
// for (;;) {
// System.out.println("三个都不写");
// }
}
}
public class Test {
public static void main(String[] args) {
//计算 1~100 的累计和,当累加和等于3000时,累加到那个数字
//存储累加和
int sum = 0;
for (int i = 1;i<=100;i++) {
sum += i;
if (sum == 3000) {
System.out.println(i);
}
}
}
}
public class Test {
public static void main(String[] args) {
//计算1~100之间所有的偶数,5个一行打印输出
//存储累加和
int sum = 0;
//记录次数
int count = 0;
for (int i = 1;i<=100;i++) {
//判断 i 是否为 偶数
if (i%2==0) {
//count + 1
count++;
//打印内容
System.out.print(i+",");
}
//判断 count 是否等于 5
if (count == 5) {
// 重新赋值为0
count = 0;
//换行
System.out.println();
}
}
}
}
public class Test {
public static void main(String[] args) {
//小明有20块钱,去买可乐,一瓶可乐3块,每个瓶盖可以抵1块,问小明可以喝多少瓶可乐。
//用户输入金额,输入喝饮料金额,查看能喝多少瓶
Scanner sc = new Scanner(System.in);
System.out.println("请输入金额》》》");
int sum = sc.nextInt();
System.out.println("请输入饮料价格》》》");
int num = sc.nextInt();
//区间次数
int count = 0;
//总次数
int count2 = 0;
//循环判断,用户可以买几瓶
while (sum>num) {
//计算购买次数
count = sum / num;
//将次数赋值给总次数
count2 += count;
//获取剩余的钱 + 购买次数
sum = sum % num + count;
}
System.out.println(count2);
}
}
public class Test {
public static void main(String[] args) {
/*
* 九九乘法表,一共九层
* 每层都是从1开始计算,直到当前层数
* 1*1=1
* 1*1=1 1*2=2
* 1*1=1 1*2=2 1*3=3
*/
//外层循环控制次数
for (int i = 1;i<=9;i++) {
//里面循环,进行计算和打印
for (int j = 1;j<=i;j++) {
System.out.print(j + "*" + i + "=" + (i*j) + "\t");
}
//换行
System.out.println();
}
}
}
执行顺序
- 初始化变量
- 判断条件,条件为 true,则执行一次,条件变更,依次执行
- 条件为 false 时,则循环终止,执行后续代码
注意事项
- 在死循环下面,写程序会报错,因为程序不可达
- for 循环和 while 循环很像,for 循环能做的事情,while 也能做,只不过使用场景不同
- 将初始值写在 for 循环的括号里,减少内存的开支,而且初始变量的作用范围也缩小了
- 循环可以嵌套
3.6.3 break 和 continue
3.6.3.1 break
break 跳出当前循环
public class Test {
public static void main(String[] args) {
//循环1~100
for (int i = 1;i<=100;i++) {
//输出循环次数
System.out.println(i);
//i == 50
if (i == 50) {
//跳出循环
break;
}
}
}
}
3.6.3.2 continue
continue 跳过本次循环,执行下一次
public class Test {
public static void main(String[] args) {
//循环1~100
for (int i = 1;i<=100;i++) {
//判断
if (i%2==0) {
//跳出本次循环继续下一次
continue;
}
//如果 i 是基数,则打印输出
System.out.println(i);
}
}
}
3.7 方法
3.7.1 方法是什么?
方法就是一段特殊功能代码的集合,它里面封装了特殊功能的代码,从而达到复用性
3.7.2 方法的使用
语法
修饰符 [static] {
void|数据类型} 方法名(形参1,形参2) {
方法体
[return |数据类型;]
}
// 修饰符 表示当前方法的访问权限
// static 静态、唯一、共享,属于类
// void 无返回数据类型
// 数据类型 表示你要返回那些数据类型,数据类型可以是基本数据类型,也可以是引用数据类型
// 方法名 相当于人的名字,用于寻找方法
// 参数 可以理解,传递的数据,这些数据是有数据类型的
// return 终止程序,返回内容
示例
public class Test02 {
// 这是一个无参的方法
public static void test01() {
for (int i = 1;i<=9;i++) {
for (int j = 1;j<=i;j++) {
System.out.print(j+"*"+i+"="+(j*i)+"\t");
}
System.out.println();
}
}
/*
* 有参方法的参数,是根据现实的业务需求来决定的
* 比如:我要写一个能够实现三位操作数的加法运算的方法
* 首先三位操作数,是不是就对应者三个变量
* 那么方法中,就要定义三个形参
* 注意:
* 1、方法中参数,被称为形参,实际传入的值,被称为实参
* 2、方法中参数,相当于我们之前定义的变量,只不过方法参数的值,是谁调用,有谁来赋值
* 3、方法中参数,可以定义一个或多个,参数是有数据类型的,参数定义完成后,是有顺序的
* 在调用方法时,传入参数就要遵循方法参数的数据类型和顺序
*/
public static void add(int num,double num2,long num3) {
System.out.println(num+num2+num3);
}
public static void main(String[] args) {
//无参方法的调用:方法名();
test01();
/*
* 有参方法的调用:方法名(参数值1,参数值2....)
* 方法的参数,定义了多少个就要传递多少个,且数据类型和顺序不能乱
*/
add(20,36.5d,60L);
}
}
注意事项
-
方法的类型有:无参方法和有参方法
-
有参方法中的参数,一旦定义,在调用传值时,就必须遵循其顺序和数据类型
-
方法中的参数,是调用者负责传参的
-
有参方法中的参数,可以定义一个或多个,具体还是根据业务需求来决定的
3.7.3 方法的返回值
示例
public class Test {
//计算两数之和,并*2,将其打印出来
public static void add(int num,int num2) {
System.out.println((num+num2)*2);
}
//计算三数之和,并*2,将其结果返回
public static int add2(int num,int num2,int num3) {
return (num+num2+num3)*2;
}
public static void main(String[] args) {
add(10,20);
System.out.println(add2(20,10,25));
}
}
注意事项
-
当方法带有 void 表示,此方法无返回值
-
如果我们要方法执行完毕后,向调用者返回一个内容,那么就需要返回值
-
返回的数据类型是什么,void 就要被替换成什么类型,return 就要返回什么类型
-
方法什么时候,需要返回值?什么时候不需要?
- 看业务需求,看调用者是否需要方法返回一个值,进行操作
-
当方法中带有 void ,我们仍然可以使用 return ,只不过不能返回任何数据
public static void add() { return; }
3.7.4 方法的重载
-
方法的重载就是:同类,不同操作
-
两同
- 同名、同类
-
三不同(参数列表)
- 个数不同
- 顺序不同
- 类型不同
-
方法的重载与返回值和方法名无关
-
方法重载参数类型匹配机制
- 先匹配,自身数据类型
- 方法的重载方式
-
示例
-
public class Test { public static int add(int num,int num2) { return num+num2; } //个数不同 public static int add(int num,int num2,int num3) { return num+num2+num3; } //类型不同 public static int add(double num,int num2) { return (int)num+num2; } //顺序不同 public static int add(int num,double num2) { return num+(int)num2; } //返回值不同,不够成重载 // public static double add(int num,double num2) { // return 0.0d; // } //数据类型相同,变量名不同,不构成方法的重载 // public static double add(int a,double b) { // return 0.1d; // } }
3.7.5 练习
-
示例
-
public class Test { //返回水仙花数 public static int test01(int num) { //计算数字的长度 int length = length(num); //存储数字 int num2 = num; //存储累加和 int sum = 0; //循环计算吧 while(num != 0) { //获取最后一位 int bit = num%10; //计算 当前数^length 平方之和,进行累加 sum += pow(bit,length); //移除最后一位 num /= 10; } //判断是否是水仙数 if (sum == num2) { return sum; } //不是就返回 0 return 0; } //将一个数,倒叙输出 public static void test02(int num) { //获取数字的长度 int length = length(num); //存储累加和 int sum = 0; //循环,计算 for (int i = 1;i<=length;i++) { //获取最后一位 int bit = num%10; //计算 bit * 10^length - 当前位数 sum += (bit*(length-i==0?1:pow(10,(length-i)))); //移除最后一位 num /= 10; } //打印输出 System.out.println(sum); } //根据用户输入的金额和饮料的单价,来判断总金额可以买几瓶 public static void test03(int num,int num2) { //区间记录购买次数 int count = 0; //总记录购买次数 int count2 = 0; //循环,计算 while (num>num2){ //总金额 / 单价,获取购买次数 count = num / num2; //将区间的购买次数,赋值给总购买次数 count2 += count; //获取剩余的金额,加上购买次数 num = (num % num2) + count; } //打印输出 System.out.println(count2); } //用户输入年月日,判断当前年的时间离当前年的初始第一天,距离多少天 public static void dateDay() throws InputMismatchException{ //创建 Scanner 对象 Scanner scanner = new Scanner(System.in); System.out.println("请输入年份"); int year = scanner.nextInt(); System.out.println("请输入月份"); int month = scanner.nextInt(); System.out.println("请输入日期"); int day = scanner.nextInt(); //定义总天数 int maxDay = 0; //获取当前月份之前的天数 for (int i = 1;i<day;i++) { //偶数月为30,基数月为31 if (i%2==0) { maxDay += 30; }else { maxDay += 31; } } //判断是否是闰年,还是平年 //闰年(1)年份能被4整除,但不能被100整除;(2)能被400整除 //闰年 2 月 29天,平年 2 月 28 天 if (((year % 4 == 0) && year % 100 != 0)||year % 400 == 0) { maxDay -= 1; }else { maxDay -= 2; } //打印天数 System.out.println(maxDay); } //键盘输入,并将结果返回 public static int scannerIn() { //创建 Scanner 对象 Scanner scanner = new Scanner(System.in); System.out.println("请输入数字"); //判断输入的内容是否是数字 if (!scanner.hasNextInt()) { //抛出错误 throw new InputMismatchException("请正确输入内容"); } return scanner.nextInt(); } //计算平方之和的方法,并将数字返回 public static int pow(int num,int pow) { //接受数字 int rest = num; //循环,计算平方和 for (int i = 1;i<pow;i++) { //rest = rest * num; rest *= num; } //返回内容 return rest; } //计算数字长度的方法,将数字的长度返回 public static int length(int num) { //记录次数 int index = 0; //循环,计算 while(num != 0) { num /= 10; index++; } //返回内容 return index; } public static void main(String[] args) { // System.out.println(test01(153)); // test02(103456); // test03(20,3); dateDay(); } }
-
注意事项
- 方法在定义时,先结果,再过程
- 减少代码的冗余,判断业务中,是否有其他代码和此方法中的逻辑一样,如一样,提出来,单独写个方法
- 简化代码,排除错误
- 可以试着将方法中其他逻辑查分,由当前方法调用
3.8 递归
递归是什么?
递归就是自己调用自己,递归分为递归头和递归体。
递归头就是判断程序什么时候结束,递归体就是执行的逻辑代码。
递归一般用于打印 树结构,其他的不怎么常用
递归语法简单,但是十分耗内存资源
示例
public class Test {
//计算斐波那契数列
public static int test01(int num) {
if (num == 1||num == 2) {
return 1;
}
return test01(num-1)+test01(num-2);
}
//计算阶乘
public static int test02(int num) {
if (num == 1) {
return 1;
}
return num*(num-1);
}
}
第四章 面向对象
4.1 什么是面向过程?
-
面向过程是执行者思维
-
面向过程是按照步骤去执行?
-
我们开车回家?那么开车回家有哪些步骤?
- 开门,进车
- 插上钥匙,启动
- 确定路线,出发
- 将车停机停车场
- 下车,回家
-
面向过程虽然是按照步骤去执行的,但是很多时候都是从无到有(根据事情不同)
-
所以面向过程只适合做简单的事情,面对复杂的事情,反而会很困难
4.2 什么是面向对象?
- 面向对象是设计者思维,更加贴合人的语言和人的逻辑
- 那么它是如何去工作的?
- 比如造车?车由哪些部分组成?
- 轮胎
- 发动机
- 座椅
- 玻璃
- 车壳
- 首先面向对象不会去管,这些东西是什么生产的,它会将这些东西交给不同的厂商去生产,进行组成,就 ok 了
- 如果这些东西你要让面向过程去做?是不是很复杂的
- 所以面向对象适合处理复杂且多人协作的事情
4.3 面向过程和面向过程的总结
-
都是解决问题的思路
-
宏观上面向对象负责整体的架构设计
-
微观上面向过程负责去执行和调用
-
所以面向对象离不开,面向过程
-
而面向过程不需要面向对象
4.4 类和对象的关系
4.4.1 什么是类?
-
类可以看做是一个现实事物的模板,也可以看做是虚拟事物的模板
-
类具有现实事物的属性和行为
-
比如人?图解
-
类可以包含
- 属性(变量)
- 成员属性
- 静态属性
- 方法
- 方法
- 成员方法
- 静态方法
- 构造方法
- 属性(变量)
-
什么是成员变量和成员方法?
- 在方法之外,类之内里面的变量和方法
- 没有被 static 修饰的属性和方法
- 成员属性和成员方法属于对象,只能通过对象来调用
-
成员属性的默认值
- 整数类型:0
- 字符类型:空字符
- 布尔类型:false
- 浮点型:0.0
- 引用类型:null
-
局部变量
- 局部变量就是指在方法中定义的变量,也就是方法中 { } 中定义的变量
4.4.2 什么是对象
-
类可以看做是现实事物和虚拟事物的模板
-
那么对象就可以看做是这个模板具体实现,同时也是一个具体事物的实现
-
类就是对象的模板,我们通过这个模板,定义n个对象
-
示例
//定义一个学生类 public class Student { //姓名 public String name; //年龄 public int age; //性别 public char sex; //专业 public String major; //学校 public String school; //班级 public String classs; public void eat() { System.out.println("吃饭"); } public void sun() { System.out.println("运动"); } public void study() { System.out.println("学习"); } public void homework() { System.out.println("写作业"); } public static void main(String[] args) { //创建对象 //类名 变量名 = new 类名(); Student student = new Student(); //调用方法 student.eat(); student.study(); //调用属性,赋值 student.name = "小丁"; student.age = 20; student.sex = '男'; //打印属性 System.out.println(student.name); } }
4.5 构造器
4.5.1 什么是构造器?
- 构造器也叫构造方法,用于初始化对象,并给对象属性赋值
- 创建对象时,默认调用无参构造器,目的是对象的初始化
- Java 通过 new 关键字来调用构造器,从而返回该类的实例
4.5.2 构造器的分类
- 无参构造(默认创建)
- 有参构造
4.5.3 构造器的语法
//无参构造
public 类名() {
}
//有参构造
public 类名(属性1,属性2...){
this.属性1 = 属性1;
this.属性2 = 属性2;
}
4.5.4 构造器的使用
public class Dog {
public String name;
public int age;
public char sex;
//无参构造器,在对象创建是默认调用,前提是无参对象
public Dog() {
System.out.println("调用了无参构造方法");
}
//有参对象
public Dog(String name,int age,char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void behavior() {
System.out.println("摇尾巴");
}
public static void main(String[] args) {
//无参对象,在创建对象时,默认调用无参构造方法
Dog dog = new Dog();
//有参构造
Dog dog2 = new Dog("小黄",20,'男');
System.out.println(dog);
}
}
注意事项
- 无参构造器,不需要创建,在创建无参对象时,默认调用
- 有参构造器一旦创建,默认构造器就不会在自动创建了
- 建议,编写类时,手动把无参构造器写上
- 构造器通过 new 关键字调用!
- 构造器虽然有返回值,但是不能指定其返回类型(返回值的类型是本类),不能在构造器里面使用 return 返回某个值,但可以使用 return;
- 构造的方法名必须和类名一样
对象的创建是由构造方法实现的吗?
- 不安全是,构造是 Java 创建对象的重要途径之一,在调用 new 关键字时,确实返回该类的实例,但是对象的创建,并不完全是由构造器实现的
- 对象的创建分为一下几个步骤
- 分配对象空间,并将对象成员变量初始化为0 会 null
- 执行属性值的显示初始化
- 执行构造方法
- 返回对象的地址给相关的变量
4.5.5 构造器的重载
-
我们可以根据需求,来对象相应的属性赋值
-
public class Dog { public String name; public int age; public char sex; //无参构造器,在对象创建是默认调用,前提是无参对象 public Dog() { System.out.println("调用了无参构造方法"); } //有参构造器1 public Dog(String name,int age,char sex) { this.name = name; this.age = age; this.sex = sex; } //有参构造器2 public Dog(String name,int age) { this.name = name; this.age = age; } //有参构造器3 public Dog(int age,char sex) { this.age = age; this.sex = sex; } public void behavior() { System.out.println("摇尾巴"); } public static void main(String[] args) { //创建对象 Dog dog = new Dog("小黄",2,'雄'); Dog dog2 = new Dog("狗蛋",3); Dog dog3 = new Dog(1,'雌'); //打印内容 System.out.println(dog.name + ","+dog.age + "," + dog.sex); System.out.println(dog2.name + "," + dog2.age + "," +dog2.sex); System.out.println(dog3.name + "," + dog3.age + "," + dog3.sex); } }
注意事项
-
this 表示当前对象
-
当构造器里面的形参名与属性名一致时,需要使用 this 进行指定哪个是对象的属性,哪个是形参
public class Dog() { public int age; public Dog(int age) { //this.age 表示当前对象的属性,age表示构造的形参 this.age = age; } }
4.6 值的传递机制
-
基本数据类型,在传递值时,传递的是副本数据,其值不会发生改变
-
引用类型,在传递值时,传递的是地址,如果对这个地址做了一些操作,外面的那个引用类型的值会发生改变
-
public class Test { //基本数据类型,在传递值时,传递的是副本数据,其值不会发生改变 public void test01(int num) { num += 10; System.out.println("里面num的值:"+num); } //引用类型,在传递值是,传递的是地址,如果方法对这个地址做出改变,那么外面那个引用类型的值会发生改变 public void test02(int[] arry) { //将数据内容的值位置对换 for (int i = 0;i<arry.length/2;i++) { //获取当前索引值 int num2 = arry[i]; //获取 arry.length - (i+1) 索引的值 arry[i] = arry[arry.length - (i+1)]; //将 num2 的值 赋值给 arry.legnth - (i+1)的索引 arry[arry.length - (i+1)] = num2; } //打印内容 System.out.println("里面arry数组的内容:"+Arrays.toString(arry)); } public static void main(String[] args) { //创建 Test 对象 Test test = new Test(); //定义基本数据类型 int num = 10; //定义数据 int[] arry = { 1,2,3,4,5,6,7,8,9,10}; //调用基本数据类型,传值的方法 test.test01(num); System.out.println("外面num的值:"+num); //调用引用类型,传值的方法 test.test02(arry); System.out.println("外面arry数组的值:" + Arrays.toString(arry)); } }
4.7 垃圾回收机制
4.7.1 垃圾回收机制介绍
- 每个程序员都遇到过内存溢出的情况,程序运行时,内存空间是有限的,那么如何及时的把不再使用的
对象清除将内存释放出来,这就是GC要做的事。 - 说起垃圾回收机制(GC),大部分人都把这项技术当做Java语言的伴生产物。事实上,GC的历史比Java
久远,早在1960年Lisp这门语言中就使用了内存动态分配和垃圾回收技术 - 程序员们知道,jvm内存结构分为五大区域:程序计数器、虚拟机栈、本地方法栈、堆区、方法区
- 其中虚拟机栈、本地方法栈与程序计数器这3个区域随线程而生、随线程而灭,因此就不需要考虑过多内存垃圾回收问题,因为一个方法调用结束或者线程结束时,内存自然就跟随着回收了
- 我们就把重点放在方法区与堆区,这部分内存的分配和回收是动态的,正是垃圾收集器所需关注的部分
4.7.2 不用语言下对象空间的释放
- 传统的C/C++语言,需要程序员负责回收已经分配内存。显式回收垃圾回收的缺点
- 程序忘记及时回收,从而导致内存泄露,降低系统性能
- 程序错误回收程序核心类库的内存,导致系统崩溃
- Java语言不需要程序员直接控制内存回收,是由JRE在后台自动回收不再使用的内存,称为垃圾回收机制(Garbage Collection)
- 可以提高编程效率
- 保护程序的完整性
- 其开销影响性能。Java虚拟机必须跟踪程序中有用的对象,确定哪些是无用的
4.7.3 垃圾回收机制的关键点
-
垃圾回收机制只回收JVM堆内存里的对象空间
-
对其他物理连接,比如数据库连接、输入流输出流、Socket连接无能为力
-
现在的JVM有多种垃圾回收实现算法,表现各异
-
垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行
-
可以将对象的引用变量设置为null,暗示垃圾回收机制可以回收该对象
-
程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有一些效果,但是系统是否进行垃圾回收依然不确定
-
垃圾回收机制回收任何对象之前,总会先调用它的finalize方法(如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象)
-
永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用
4.8 this 和 static 关键
4.8.1 this 关键字
-
this 表示当前对象
-
在构造器中 this 表示当前对象,在普通方法中 this 表示 调用这个方法的对象
-
this 可以用于构造器的重载,必须位于构造器的第一行
- 调用方法 this(形参值) 根据形参值区分构造器
-
在方法中如定义其和成员属性名一致的变量,需要使用 [this|对象名|类名].属性,否则默认就近原则
-
构造器之间不能相互调用
-
public class TestThis { public static void main(String[] args) { //创建对象 Dog dog = new Dog("小丁",25,'男'); } } class Dog { public String name; public int age; public char sex; public Dog() { System.out.println("执行了无参构造"); } /*public Dog(String name,int age,char sex) { 形参名与成员属性名一致,不使用 this 指定其对象属性名,则自己给自己赋值 name = name; age = age; sex = sex; }*/ public Dog(String name,int age) { //调用无参构造 this(); this.name = name; this.age = age; System.out.println("执行了有参构造1"); } public Dog(String name, int age, char sex) { //调用有参构造 this(name,age); this.sex = sex; System.out.println("执行了有参构造2"); } }
4.8.2 static 关键字
4.8.2.1 static 介绍
-
静态属于类,成员属于对象
-
static 只能修饰成员属性和方法
-
被 static 修饰的成员属性和成员方法是静态的、唯一的、被所有实例共享的,隶属于类
-
static 方法,不能访问非 static 成员,想要访问必须通过对象名或者创建对象
-
在类被加载时,会将被 static 修饰的成员变量和方法,在静态区中进行初始化
-
被 static 修饰的属性和方法被称为 静态属性和静态方法 或者 类属性和类方法
-
在成员方法中可以访问:静态属性和静态方法
-
调用方式
- [类名|对象名].[属性|方法]
-
this 不能在 static 方法中使用
-
public class TestStatic { public static void main(String[] args) { //创建对象 Student stu = new Student(); Student stu2 = new Student(); //调用类属性和类方法 Student.major = "Java开发"; Student.eat(); //通过对象调用类属性 System.out.println(stu.major); System.out.println(stu2.major); //验证是否唯一 stu.major = "阿里巴巴"; System.out.println(stu.major); System<