基础通用语法
一、标识符Identifier
1、什么是标识符:
- 凡是程序员有权利自己命名的单词都是标识符,EditPlus中是黑色高亮显示
- 类名,变量名,方法名,接口名,常量名
public class IdentifierTest{ //IdentifierTest是类名
public static void main(String[] args){ //main是方法名,args是变量名
}
public static void doSome(){ // doSome是方法名
int i = 10; //i是变量名
}
}
2、标识符的命名规则:(不遵守会报错,如法律)
- 标识符只可以含有——字母、数字、下划线、美元符号。
- 不能以数字开头
- 严格区分大小写
- 关键字不可以作标识符,public、class、static
合法 | 不合法 |
---|---|
HelloWord | Hello Word |
public1 | public |
class1 | class |
$abc | 123a |
A_b_c | public# |
3、标识符的命名规范:(不遵守会被谴责,如道德)
- 最好见名知意
- 遵守驼峰命名方法——UserService
- 类名、接口名 —— 第一个单词首字母大写,后面单词全部首字母大写
- 变量名、方法名 —— 第一个单词首字母小写,后面单词全部首字母大写
- 常量名 —— 全部大写
public class UserService{ //一看就知道关于用户服务的
//一看就知道是登陆方法,含有用户名和密码
public void login(String username,String password){
}
}
二、常见关键字(均小写)
class 。extends。implements实现。 interface接口 。 import导入包 。package包装 。 break 。 continue 。 default。 do 。 if 。 else 。for 。 return。 switch 。case 。while 。 false 。true 。 null 。boolean。 byte。 char 。 short 。 int 。long 。 float 。 double 。 try 。 catch 。throw。 throws 。 finally 。 abstract 。 final 。 private。 protected 。 public 。 static 。 synchronized线程的锁 。 transient 。volatile。 instancof 。 new 。 super 。 void 。 assert 。enum 。 goto 。 const。 native。
三、字面值Const
字面值:就是数据,就是值,是分类型的【数据类型】
10 、100 | 整数型 |
---|---|
3.14 | 浮点型 |
“abc” | 字符串 |
‘a’ | 字符 |
true 、 false | 布尔型 |
字符串必须英文半角双引号,字符必须是英文半角单引号,单引号里面只能存放单个字符
四、变量Var
(一)、基础概念
1、什么是变量
- 就是内存开辟的一块空间
- 包含三个部分:数据类型、标识符名称、字面值
- 变量是内存中存储数据的最基本的单元
2、数据类型的作用
- 不同的数据类型会分配不同的大小空间
- 数据类型指导系统在运行阶段分配多大空间
3、变量要求
- 变量中存储的字面值的类型必须和变量的数据类型一致,不能int i = “阿巴阿巴”
- 声明/定义变量的格式
数据类型 变量名;
4、变量赋值
i = 100;
- =等号是赋值运算符,先运算等号右边的表达式,再赋值给左边
- 变量赋值后可重新赋值,变量的值可变化
- 有了变量的概念之后,变量可以被重复访问,i可以被重复输出
int i = 10;
system.out.println( i ); //10
system.out.println( i ); //10
system.out.println( i ); //10
5、访问变量有两种访问方式
- 读取变量中具体数据 get/获取
- 修改变量中具体数据 set/设置
int = 20; //set
system.out.println ( i ); //get
6、变量可以同时声明、赋值多个
int a , b , c = 1,2,3;
int a , b , c = 300; // a和b尚未初始化,c是300
7、先声明,再赋值之后,变量才完成初始化,才可以访问
成员变量有默认值,成员变量没有
public class Var{
public static void main(String[] args){
int i = 10;
//访问不成功,编译会报错,变量未初始化
//System.out.println( i );
i = 10;
// 正常访问,声明+赋值=正常初始化
System.out.println( i ); // 10
}
}
8、运行顺序是自上而下
在方法体中,运行顺序是自上而下的,上一行代码必须完整结束之后,下一行程序才会执行
public class Var{
public static void main(String[] args){
// 程序报错,因为没有先开辟内存空间,不知道k,就无法访问k
/*
System.out.println( k );
int k = 10;
*/
}
}
public class Var{
public static void main(String[] args){
int i = 10;
System.out.println( i ); //10
// 这是重新赋值,因为已经开辟空间是i
i = 20;
System.out.println( i ); // 20
//编译报错。
//已经初始化变量i,再初始化一个的话JVM就不知道是谁,会报错
/*
int i =30;
*/
}
}
(二)、变量的作用域
1、什么是作用域
- 描述的就是变量的有效范围,其实就是一个大括号之内
- 作用域就是指在什么范围内可以被访问,出了这个范围,该变量就无法访问了
public class Var{
static int k =10;
public static void main (String[] args){
// 变量i的作用域就是main方法,只有在main方法中才是有效的
int i = 10;
System.out.println( i ); //可以
System.out.println( k ); //可以
}
public static void doSome( ){
//这里无法访问main方法中的变量,已经出了i变量的作用域,报错
System.out.println( i ); //不可以
System.out.println( k ); //可以
}
}
循环中的作用域
public class Var{
public static void main (String[] args){
for( int a = 1;a<10;a++){ //作用域是这个for循环
}
//这里无法访问a变量,for循环结束之后a的内存就被释放了
System.out.println( a ); //不可以
int b ; //作用域是main方法
for( int b = 1; b <10; b ++){ //可以
}
System.out.println( b ); //可以
}
}
2、变量的分类
根据声明的位置来分类,局部变量,成员变量
- 局部变量:在方法体内声明的变量
- 成员变量:在方法体外类体内声明的变量
public class Var{
public static void main( String[] args){
//局部变量
int i = 10;
}
//成员变量
int i = 20;
public static void doSome(){
//局部变量
int i = 100;
}
}
- 在不同的作用域中,变量名可以重名
- 在同一个作用域内,变量名不可重名
- 运行采用"就近原则"
public class Var{
public static void main( String[] args){
int i = 10;
System.out,println( i ); // 10
}
int i = 20;
}
public class Var{
public static void main( String[] args){
// 运行采用"就近原则"
System.out,println( i ); // 20
}
static Int i = 20;
}
五、数据类型DataType
- 引用数据类型
- 基本数据类型
四大类八小种
- 整数型
byte,short,int,long - 浮点型
float,double - 布尔型
boolean - 字符型
char
1、取值范围
类型 | 取值范围 |
---|---|
byte | [ -128 ~ 127] |
short | [-32768 ~ 32767] |
int | [-2147483648 ~ 2147483647] |
long | |
float | |
double | |
boolean | [false , true] |
char | [0 ~ 65535] |
注意:short和char类型所表示的类总数是一样的,只不过char没有负数,二者表示的区间是一样大的
2、默认值
数据类型 | 默认值 |
---|---|
byte,short,int,long | 0 |
float | 0.0 |
boolean | false |
char | \u0000 |
public class Test {
//只有成员变量才可以默认赋值【局部变量不可以】
static int i;
static int j = 20;
public static void main(String[] args) {
int k = 10;
System.out.println(k);
//main方法是静态方法
//访问成员变量只有加了static的变量才可以访问,否则报错
System.out.println(i); //0
System.out.println(j); //20
}
}
3、字符型char
public class Taet{
public static void main(String[] args){
char c = 'a';
System.out.println(c); //a
char b = '中';
System.out.println(b); //中
//编译错误。ab是字符串,不能用单引号
/*
char d ='ab';
*/
//编译错误。"a"是字符串类型,类型不兼容
/*
char e ="a";
*/
}
}
4、转义符 \
- 转义符出现在特殊字符之前,会将特殊字符转换为普通字符
- \ n 换行符
- \ t 制表符,就是tab键
- \ \ 普通的反斜杠
- \ ’ 普通的单引号
- \ " 普通的双引号
- char的默认值是 \ u0000
\ n 换行符; \ t 制表符
public class Test {
public static void main(String[] args) {
char a ='n';
System.out.println(a); //n
//换行符
a='\n';
//System.out.print()和System.out.println()的区别是
// println输出之后换行,print输出之后不换行
System.out.print("Hello");
System.out.println("Word"); //HelloWord
System.out.println("Hello"); //Hello
System.out.println("Word"); //Word
//用上换行符
System.out.print("Hello");
System.out.print(a); //Hello
System.out.println("Word"); //Word
//制表符
char b = '\t';
//制表符和空格不一样,它们的ASCII不一样,键盘按键不一样
System.out.print("A");
System.out.print(b);
System.out.println("B"); //A B
}
}
\ \ 普通的反斜杠 ; \ ’ 普通的单引号 ; \ " 普通的双引号
public class Test {
public static void main(String[] args) {
//要求在控制台输出“反斜杠字符”
//编译报错。反斜杠将后面的单引号变成了普通的字符
//左边的单引号缺少了结束的单引号
/*
char a ='\';
*/
char a = '\\';
System.out.println(a); // \
//要求在控制台输出“单引号”“双引号”
//编译报错。不可为空
/*
char b ='';
*/
//编译报错。第一个与第二个单引号配对,第三个找不到另一半
/*
char b =''';
*/
char b ='\'';
System.out.println(b); // '
char c ='"';
System.out.println(c); // "
System.out.println("\"ABCD\""); //"ABCD"
}
}
5、整数型
数据类型 | 占用空间 | 默认值 | 取值范围 |
---|---|---|---|
byte | 1 | 0 | [ -128 ~ 127 ] |
short | 2 | 0 | [ -32768 ~ 32767 ] |
int | 4 | 0 | [ -2147483648 ~ 2147483647 ] |
long | 8 | 0L |
- Java中的整数字面值默认是 int 类型,若想是 long 类型的数字,就需要加 L,比如 long i = 10L
- Java中字面值可以是十进制、八进制、十六进制,但是输出结果都是十进制。(八进制是0开头,十六进制是0x开头)
public class Test{
public static void main(String[] args){
int a = 10;
int b = 010; //整数字面值以0开头就是八进制
int c = 0x10; //整数字面值以0x开头就是十六进制
//Java认十进制
System.out.println(a); // 10
System.out.println(b); // 8
System.out.println(c); // 16
}
}
6、浮点型
float —— 单精度 —— 4个字节
double —— 双精度 —— 8个字节
相对来说double的精度太低,不适用于财务软件,所以有精度更高的类型,是引用数据类型,java.math.BigDecimal
注意:
- Java中所有浮点型字面值默认为double类型,要想字面值是float类型,就在字面值后面加 F / f
- double和float在计算机内储存的都是近似值,循环小数3.33333333…,计算机内存是有限的,无法存储无限的小数,所以存储近似值
public class Test{
public static void main(String[] args){
//右边是默认的double类型,左边是double类型,没有类型转换
double a = 1.0;
//右边是double类型,大容量转换小容量,需要强制转换
/*
float b = 1.2;
*/
//用强制转换符
float b = (double)1.1;
//让右边数值一上来就是float类型,没有类型转换
float c = 1.3F;
}
}
7、布尔型
- 布尔型只有两个值:true,false
- 经常使用在逻辑运算和条件语句中
public class Test{
public static void main(String[] args){
//编译报错。左右类型不兼容,右边是int,左边是boolean
/*
boolean a = 1;
*/
boolean a = true;
//if语句【条件控制语句】
if(a){
System.out.println("成功"); //输出结果是"成功"
}elae{
System.out.println("失败");
};
}
}
8、数据类型转换
转换规则:
- 八种类型除了boolean之外都可以互相转换
- 小容量转大容量是自动转换,大转小是强制转换,强制转换会损失精度,谨慎使用
- byte < short = char < int < long < float < double 任何浮点型大于任何整数型
- 当整数型字面值没有超过 byte、short、char 的取值范围,可以直接赋值 —— char a = 10; —— byte b = 10;
- byte、short 、char 混合运算时,会先转换成 int 类型再做运算
- 多种数据类型混合运算时,先转换成容量最大的哪种类型再做运算
- byte b = 1; —— 正确的
- int i = 1; byte c = i / 2; —— 会报错,只会看你的右边类型是 int 类型,容量大,不会帮你算出 1/2 是 byte 的取值范围内
几种少见的特殊情况
public class Test{
public static void main(String[] args){
long a = 10L;
//编译报错。右边是 int 类型,容量大,需要强制转换才可以
//编译器不会帮你算得出右边的最后结果是否在 byte 的取值范围内
byte b = (byte)(int)a/2; //错误
byte c = (byte)(int)(a/2); //正确
byte x = 1;
short y = 2;
//右边先转换成int再运算,所以是int类型,需转换
short z = x+y; //错误
short k = (short)(x+y); //正确
int l = x+y; //正确
char i = 'a';
System.out.println((byte)i); // 97,a的ASCII码
double dd = 10/3; //结果是3.0
double dd = 10.0 / 3; //结果是3.33333333335
}
}
小变大。自动转换
public class Test{
public static void main(String[] args){
//右边是默认int类型,左边是int类型,没有类型转换
int a = 10; //没有类型转换
//右边是默认int类型,左边是long类型,存在类型转换
//int类型占用4字节,long占用8字节
//小容量自动转换大容量,是自动类型转换机制
long b = 2147483647; //存在类型转换
//编译报错。右边2147483648默认为int类型,但是字面值过大,报错
/*
long c = 2147483648;
*/
//解决:把2147483648一上来就当做long类型处理,在字面值后加 L
//右边是long类型,左边也是long类型,没有类型转换
long c = 2147483648L; //没有类型转换
}
}
大变小。强制转换
public class Test{
public static void main(String[] args){
//右边是long类型,左边是int类型,需要类型转换
/*
int x = 100L;
*/
//大容量转换小容量,需要进行强制转换
//强制类型转换需要加上“强制转换符”,不推荐,会损失精度
int x = (int)10L;
}
}
六、运算符
1、算术运算法
+ | 求和 |
---|---|
- | 相减 |
* | 乘积 |
/ | 商 |
% | 求余数【取模】 |
+ + | 自加1 |
- - | 自减1 |
- 一个表达式有多个运算符时,运算符的优先级,不确定的可以加小括号,没必要记忆
- ++可以出现在变量前或者后,无论前后,++运算结束后,变量都会自加1
- 当赋值与++同时存在时,++在变量前,就进行自加1运算,然后再进行赋值操作;++在变量后,就先赋值再自加1。
- 运算符前后加一个空格
public class Test{
public static void main(String[] args){
int i = 10;
int j = 3;
System.out.println(i + j); //13
System.out.println(i - j); //7
System.out.println(i * j); //7
System.out.println(i / j); //3
System.out.println(i % j); //1
}
}
以下以自加1++为例,- -符号自学
public class Test{
public static void main(String[] args){
//++运算符可出现在变量前后【单目运算符】
int k = 10;
k++;
System.out.println(k); //11
++k;
System.out.println(k); //12
//++运算符和赋值运算符同时存在时
//++在变量后,就先赋值再自加1
int a = 100;
int b = a ++;
System.out.println(a); //101
System.out.println(b); //100
//++在变量前,就进行自加1运算,然后再进行赋值操作
int m = 200;
int n = ++ m;
System.out.println(m); //201
System.out.println(n); //201
/*
练习
*/
int e = 1;
System.out.println(e ++); //1
System.out.println(e); //2
int f = 7;
System.out.println(++ f); //8
System.out.println(f); //8
int i =100;
System.out.println(++ i); //101
System.out.println(-- i); //100
System.out.println(i ++); //100
System.out.println(i --); //101
System.out.println(i --); //100
System.out.println(i --); //99
System.out.println(i); //98
int x =5;
int j = 5;
System.out.println(x ++ > j); //false
System.out.println(x); //6
System.out.println(j); //5
x = 5;
j = 5;
System.out.println(++ x > j); //true
System.out.println(x); //6
System.out.println(j); //5
}
}
2、关系运算符
> | 大于 |
---|---|
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
- = 是赋值运算符,==是关系运算符。注意两个符号中间无空格
- 关系运算符的结果一定是布尔类型:true / false
- 运算原理:数据类型的 a > b 比较的时候,比较的是字面值
public class Test{
public static void main(String[] args){
int a = 10;
int b = 10;
System.out.println(a > b); //false
System.out.println(a >= b); //true
System.out.println(a < b); //false
System.out.println(a <= b); //true
System.out.println(a == b); //true
System.out.println(a != b); //false
}
}
3、逻辑运算符
- & 逻辑与【并且】,运算符两边的算子都是true,结果才是true。
- & 逻辑与【并且】,两边的算子只要有一个false,结果就是false
- | 逻辑或【或者】,两边的算子只要有一个true,结果就是true
- ! 逻辑非【取反】,单目运算符,!true结果是false,!false结果是true
- ^ 逻辑异或【不同】,两边的算子不一样,结果就是true
- && 短路与
- || 短路或
注意:
- 逻辑运算符的算子和结果都是布尔类型:true,false
- 短路与、短路或和逻辑与、逻辑或结果相同,只不过有短路现象
- 逻辑与:就算发现前面算子是false,也会执行后面的算子。
- 短路与:只要发现前面算子是false,后面算子并不执行,直接输出结果false
- 逻辑或:就算发现前面算子是true,也会执行后面的算子
- 短路或:只要发现前面算子是true,后面算子并不执行,直接输出结果true
public class Test{
public static void main(String[] args){
//不确定运算优先级可以用小括号
System.out.println(7 > 4 & 5 > 3); //true
System.out.println(true & true); //true
System.out.println(true & false); //false
System.out.println(false & true); //false
System.out.println(false & false); //false
System.out.println(false | false); //false
System.out.println(true | false); //true
System.out.println(!false); //true
System.out.println(!true); //false
System.out.println(true ^ false); //true
System.out.println(true ^ true); //false
System.out.println(false ^ false); //false
}
}
短路与、逻辑与、短路或、逻辑或
public class Test{
public static void main(String[] args){
//逻辑与
int a = 10;
int b = 5;
System.out.println(a < b & a++ > b):
System.out.println(a); //11
System.out.println(b); //5
//短路与
//因为 a<b 是false,所以后面的表达式就不再执行,短路现象
a = 10;
b = 5;
System.out.println(a < b && a++ > b):
System.out.println(a); //10
System.out.println(b); //5
}
}
4、赋值运算符
- = 基本赋值运算符
- += 、 -= 、 *= 、 /= 、 %= 扩展赋值运算符,“追加”、“追减”
注意:
- 赋值类运算符的优先级:先执行右边的表达式,再将执行结果赋值给左边的变量
- 扩展赋值运算符不改变运算结果类型,假设最初被赋值变量是byte,赋值之后仍然是byte,无论怎么进行追加和追减,最终该变量的数据类型还是byte类型
- 注意—— byte a = 10; 正确 。a += 10,相对于 a = (byte)(a + 10)
扩展赋值运算符
public class Test{
public static void main(String[] args){
//扩展赋值运算符不改变运算结果类型
//假设最初被赋值变量是byte,赋值之后仍然是byte
int a = 5;
a += 1; //相当于 a = (int)(a + 1);
byte b = 5;
b -= 4; //相当于 b = (byte)(b - 4);
long c = 5L;
int d = 5;
d += c; //相当于 d = (int)(d + c);
int x =5;
byte d = 5;
d += x; //正确,因为 b+=x 相当于 b = (byte) (b + x)
/* 编译报错,右边是int类型,左边是byte类型,大转小应该强制转换
b = b + x;
*/
byte m = 5;
m += 128; //等同于m = (byte) (m + 128) 损失精度
System.out.println(m); // -123
}
}
5、字符串连接运算符
关于Java中的 “+” 运算符:
- 有两个作用。数值加法运算求和,字符串的连接运算
- 当 “+” 运算符的两边都是数字,一定是进行加法运算
- 当 “+” 运算符两边只要有一个是字符串,一定是字符串的连接运算
- 数字 + 数字 —— “求和” ;
- 数字 + “字符串” —— “字符串连接”
- 表达式中出现多个 “+” 的时候,除了小括号,其他都是自左向依次运算
public class Test {
public static void main(String[] args) {
//要求动态输出 x + y = z
int a = 10;
int b = 8;
//输出结果: 10+8=18
System.out.println(a + "+" + b + "=" + (a + b) );
a = 5;
b = 4
//输出结果: 5+4=9
System.out.println(a + "+" + b + "=" + (a + b) );
System.out.println(10 + 8 + "30"); //1830
System.out.println(10 + (8 + "30")); //10830
}
}
引用数据类型:String类型
int 是基本数据类型 ,int a = 10 ;
String 是引用数据类型 , String s = “abc” ;
String s = 10; —— 编译错误,类型不兼容
public class Test {
public static void main(String[] args) {
//需要输出:登陆成功,欢迎xxx回来。其中xxx是动态的
String s = "caomei";
System.out.println("登陆成功,欢迎" + s +"回来");
s = "xigua";
System.out.println("登陆成功,欢迎" + s +"回来");
//登陆成功,欢迎caomei回来
//登陆成功,欢迎xigua回来
}
}
6、三元运算符 / 三目运算符 / 条件运算符
注意:
- 规则:布尔表达式 ? 表达式1:表达式2
- 当最前面的布尔表达式是 true 时,执行表达式1
- 当最前面的布尔表达式是 false 时,执行表达式2
- 注意三元运算输出的是一个结果,单纯的三元运算并不是一个Java语句
单纯的三元运算并不是一个Java语句
public class Test {
public static void main(String[] args) {
//编译报错,不是Java语句
/*
"a";
*/
//因为上面编译报错,所以下面也不是一个完整的句子
/* 编译报错,不是Java语句
3 > 2 ? "a" : "b";
*/
System.out.println("a"); //正确
//因为上面编译正确,所以下面也正确
System.out.println(3 > 2 ? "a" : "b"); //a
String s = 5 > 3 ? "a" : "b"; //正确
System.out.println(s);
//可重复赋值
s = 5 < 3 ? "a" : "b"; //正确
}
}
1、变量可重新赋值。2、需注意类型兼容问题
public class Test {
public static void main(String[] args) {
//编译报错。类型不兼容,右边是String和char混合,左边是String
/*
String s = 5 > 3 ? "a" : 'b';
*/
byte a = 10;
short b = 20;
int i = 5 > 3 ? a : b; //正确
short t = 5 > 3 ? a : b; //正确
System.out.println(i);
/*编译报错。类型不兼容。只编译,不运行
byte y = 5 > 3 ? a : b; //错误
*/
byte y = 5 > 3 ? a : (byte) b; //解决方案
}
}
七、控制语句
1、选择结构
接收用户键盘输入
- System.out.println( ); 负责向控制台输出,从内存到控制台,是输出
- 接收用户键盘输入 从键盘到内存,给某些变量输入值,是输入
第一步:创建键盘扫描器对象。第二步:调用Scanner的next( )方法
public class Test {
public static void main(String[] args) {
//第一步:创建键盘扫描器对象,知道用户键盘敲了啥
Scanner s = new Scanner(System.in);
//第二步:调用Scanner对象的next()方法,接收键盘输入。
//程序等待用户输入,输入结束回车之后内容会自动赋值给 inputContent
//接收内容【以字符串形式接收】
System.out.println("请输入:");
String inputContent = s.next();
//接收内容【以整数型形式接收】
//int num = s.nextInt();
//第三步:将内存中的数据输出到控制台
System.out.println("您输入了:" + inputContent);
//System.out.println(“计算结果:” + (num + 10));
}
}
if,if…else…
- if 语句中,只要有一个分支执行,整个 if 语句就结束,其他分支不执行
- 第二种编写和第四种编写,含有 else 分支,则这两种方式中所有分支必会执行其中之一。
- 所有的控制语句都是可以嵌套使用的
- if 语句如果只有一条Java语句,大括号可不写,这种写法不推荐,但是要看得懂别人写的。——if(…){ Java语句 } ——if(…)Java语句
- if 语句的四种编写
if 语句的四种编写
//第一种
if(布尔表达式){
Java语句;
Java语句;
...
}
//第二种
if(布尔表达式){
Java语句;
Java语句;
...
}else{
Java语句;
Java语句;
...
}
//第三种
if(布尔表达式){
Java语句;
Java语句;
...
}else if(布尔表达式){
Java语句;
Java语句;
...
}else if(布尔表达式){
Java语句;
Java语句;
...
}
//第四种
if(布尔表达式){
Java语句;
Java语句;
...
}else if(布尔表达式){
Java语句;
Java语句;
...
}else if(布尔表达式){
Java语句;
Java语句;
...
}else{
Java语句;
Java语句;
...
}
练习:
需求:所在位置5公里范围内若有KFC,就去吃饭
public class Test {
public static void main(String[] args) {
//需求:所在位置5公里范围内若有KFC,就去吃饭
double distance = 6;
if (distance < 5){
System.out.println("吃饭");
}else {
System.out.println("不吃饭");
}
}
}
需求:系统给定成绩,可能带小数,根据成绩判定等级,满分100。
[ 90 - 100 ] A ~~ [ 80 - 90 ) B~~ [ 70 - 80 ) C ~~[ 60 - 70 )D ~~ [ 0 - 60 ) E
public class Test {
public static void main(String[] args) {
//需求:系统给定成绩,可能带小数,根据成绩判定等级,满分100。
double score = 45;
char level = 'E';
String s = "您的成绩等级是:";
if ( 0 <= score & score <= 100) {
if (score >= 90) {
level = 'A';
} else if (score >= 80) {
level = 'B';
} else if (score >= 70) {
level = 'C';
} else if (score >= 60) {
level = 'D';
}
System.out.println(s + level);
}else {
System.out.println("您输入的数据有误");
}
}
}
需求:根据用户键盘输入的年龄判断处在哪个生命周期阶段,0-150岁
[0 - 5] 幼儿,[ 6 - 18 ]青少年,[ 19 - 50 ]壮年,[ 51 - 150 ] 老年
public class Test {
public static void main(String[] args) {
//需求:根据用户键盘输入的年龄判断处在哪个生命周期阶段
// [0 - 5] 幼儿,[ 6 - 18 ]青少年,[ 19 - 50 ]壮年,[ 51 - 150 ] 老年
Scanner s = new Scanner(System.in);
System.out.println("请输入年龄:");
int age = s.nextInt();
String level = "您处于生命周期的老年阶段";
if (age < 0 || age > 150){
level = "您提供的年龄不合法";
}else if (age <= 5){
level = "您处于生命周期的幼儿阶段";
}else if (age <= 18){
level = "您处于生命周期的青少年阶段";
}else if (age <= 50){
level = "您处于生命周期的壮年阶段";
}
System.out.println(level);
}
}
需求:判断天气。
若下雨,带伞——男,大黑伞;女,小花伞
若晴天,判断温度。
温度在30度以上——男,戴墨镜;女,擦防晒
【用嵌套;天气、温度、性别需要是键盘键入数据】
a
if 语句如果只有一条Java语句,大括号可不写,这种写法不推荐,但是要看得懂别人写的。——if(…){ Java语句 } ——if(…)Java语句
public class Test{
public static void main(String[] args){
if(true){
System.out.println("男");
}else{
System.out.println("女");
}
//上述代码可以写成:
if(true) System.out.println("男"); else System.out.println("女");
//--------------------------------------------------------------------
//以下代码错误出现在 else 一行,为什么?
if(true)
System.out.println("男");
System.out.println("阿巴阿巴");
else
System.out.println("女");
//上面代码相当于---------------------------下面的代码
if(true){
System.out.println("男");
}
System.out.println("阿巴阿巴");
else
System.out.println("女");
//因为只可以单独出现 if ,不可以单独出现 else ,所以该句出现错误
//而中间的 输出语句 是可以在 main 方法里运行的,只是缩进了一下,不影响
}
}
switch…
- switch 语句也是选择语句,也是分支语句
- 执行原理:小括号的数据与case的数据匹配,执行匹配成功的分支语句。匹配顺序是自上而下的顺序
- 匹配成功的分支执行,分支中有"break;" ,整个switch语句结束
- 匹配成功的分支执行,分支中没有"break;" ,直接进入下一个分支语句,无需进行数据匹配,直接执行。这种现象成为“case 穿透现象”,break可以避免穿透
- 若所有分支语句都没有匹配成功,当有default 语句,就执行 default 分支当中的程序
- switch 后小括号里面的数据只可以是 int 和 String 类型的数据。不可以是其他的
- 因为 byte、short、char 运算时会自动转换为int类型,所以小括号可以放 byte、short、char 类型。
- case 可以合并,合并之后相当于是或者
- switch 语句的语法结构:
switch 语句的语法结构:
switch (int / String 类型){
case int/String字面值或变量:
Java语句;
...
break;
case int/String字面值或变量:
Java语句;
...
break;
...
default :
Java语句;
}
case 可以合并,合并之后相当于是或者
//只要小括号的数据与下面合并的所有case 其中一个匹配,就执行下面的Java语句
int i = 10;
switch (i){
case 1: case 2 : case 3 :
System.out.println("啊");
}
switch 后小括号里面的数据只可以是 int 和 String 类型的数据。
因为 byte、short、char 运算时会自动转换为int类型,所以小括号可以放 byte、short、char 类型
public class Test{
public static void main(String[] args){
//编译报错,类型不兼容
/*
long a = 10L;
int b = a;
*/
//编译报错,类型不兼容
/*
long x = 20L;
switch( x ){ }
switch( true ){ }
*/
long x = 20L;
switch( (int)x ){ }
byte a = 10;
switch( a ){ }
short b = 100;
switch( b ){ }
char c = 'a';
switch( c ){ }
char cc = 97;
switch( c ){ }
String d = "abaaba";
switch( d ){ }
}
}
编写一个完整的 switch 语句
public class Test{
public static void main(String[] args){
//较为完整的 switch 语句
//接收用户输入,1 表示星期一、2 表示星期二...
Scanner s = new Scanner(System.in);
System.out.println("请输入:");
int num = s.nextInt();
switch(num){
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
default:
System.out.println("一周只有四天");
}
}
}
case 穿透
public class Test{
public static void main(String[] args){
Scanner s = new Scanner(System.in);
System.out.println("请输入:");
int num = s.nextInt();
//当num为1,输出:星期一,星期二,星期三
switch(num){
case 1:
System.out.println("星期一");
case 2:
System.out.println("星期二");
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
default:
System.out.println("一周只有四天");
}
}
}
//输出结果:星期一,星期二,星期三,星期四,一周只有四天
switch(num){
case 1:
System.out.println("星期一");
case 2:
System.out.println("星期二");
case 3:
System.out.println("星期三");
case 4:
System.out.println("星期四");
default:
System.out.println("一周只有四天");
switch 可以探测 String 类型
public class Test{
public static void main(String[] args){
//用户键入
Scanner s = new Scanner(System.in);
System.out.println("请输入星期几:");
String dayOfWeek = s.next();
//探测 String 类型
switch( dayOfWeek ){
case "星期一" :
System.out.println(1);
break;
case "星期二" :
System.out.println(2);
break;
default :
System.out.println("输入数据有误");
}
}
}
switch 可以探测 String 类型
字符 char 类型可以根据ASCII码和数字 int 类型转换
public class Test{
public static void main(String[] args){
char c = 65;
// 试用switch,输出——高级
switch(c){
case 'A':
System.out.println("高级");
break;
case 'C':
System.out.println("低级");
break;
default :
System.out.println("输入数据有误");
}
// 试用switch,输出——低级
switch(c){
case 'B':
System.out.println("高级");
break;
case 65 :
System.out.println("低级");
break;
default :
System.out.println("输入数据有误");
}
}
}
练习:
需求:制作简单计算器,实现+ - * / %
1、选择所有数据从键盘输入
2、使用 switch 语句进行判断
3、要从控制台输入三次:两个数据和一个运算符
请输入第一个数: 1
请输入运算符: +
请输入第二个数: 2
运算结果: 1 + 2 = 3
public class Test {
public static void main(String[] args) {
Scanner s1 = new Scanner(System.in);
System.out.println("请输入第一个数:");
int one = s1.nextInt();
Scanner s2 = new Scanner(System.in);
System.out.println("请输入运算符:");
String two = s1.next();
Scanner s3 = new Scanner(System.in);
System.out.println("请输入第二个数:");
int three = s1.nextInt();
switch (two){
case "+":
System.out.println(one + two + three + "=" + (one + three));
break;
case "-":
System.out.println(one + two + three + "=" + (one - three));
break;
case "*":
System.out.println(one + two + three + "=" + (one * three));
break;
case "/":
System.out.println(one + two + three + "=" + (one / three));
break;
case "%":
System.out.println(one + two + three + "=" + (one % three));
break;
default:
System.out.println("无法识别运算符!");
}
}
}
需求:系统给定成绩判断等级,有小数位,满分100。
[ 90 - 100 ] A ~~ [ 80 - 90 ) B ~~ [ 70 - 80 ) C ~~[ 60 - 70 )D ~~ [ 0 - 60 ) E
public class Test {
public static void main(String[] args) {
double d = 59.5;
double i = d / 10;
switch ((int) i){
case 9: case 10:
System.out.println("A");
break;
case 8:
System.out.println("B");
break;
case 7:
System.out.println("C");
break;
case 6:
System.out.println("D");
break;
default:
System.out.println("E");
}
}
}
2、循环结构
在程序当中总有一些需要反复执行的代码,假设没有循环结构就要重复编写,所以要把需要重复执行的代码片段放入“循环体”,再联合“计数器”,共同控制这段需要反复执行的代码。
循环有三种:
for 循环
while 循环
do… while 循环
for
- 语法结构
for ( 初始化语句;布尔表达式;更新语句){
// 是需要重复执行的代码片段【循环体】
} - 执行原理
a、先执行初始化语句,且只执行一次
b、判断布尔表达式是 true 或 false
c、若是 true ,执行循环体,再执行更新语句,再判断布尔表达式是 true 或 false
d、若是 false ,循环结束
e、只要在循环当中,布尔表达式是 false , 循环结束 - 注意点:
a、初始化语句。布尔表达式、更新语句 都不是必须的,两个分号是必须的
b、初始化语句最先执行,并且在整个语句当中只执行一次
c、布尔表达式必须是 true 或 false ,不可以是其他值
public class Test{
public static void main(String[] args){
//死循环
for( ; ; ){
System.out.println("死循环");
}
//输出 1-10 中的奇数
for( int i = 1; i <= 10; i = i + 2 ){
System.out.println("奇数:" + i);
}
//输出 1-10 中的偶数
for( int i = 1 ; i <= 10; i += 2){
System.out.println("偶数:" + i);
}
//计数器
for( int i = 10 ; i > 0; i --){ //输出 1-10
System.out.println("计数器1:" + i);
}
for( int i = 1 ; i <= 10; ){ //输出 2-11
i ++;
System.out.println("计数器2:" + i);
}
for( int i = 1 ; i <= 10; ){ //输出 1-10
System.out.println("计数器3:" + i);
i ++;
}
//输出 10 的倍数
for(int i = 100; i >= 0; i -= 10){
System.out.println("倍数:" + i);
}
}
}
i 变量的作用域
public class Test{
public static void main(String[] args){
//以下的for循环中的“i”变量作用域仅限于该循环内部使用
//这个 i 变量在main方法中无法访问
for(int i = 1; i <= 10; i ++){
System.out.println(i);
}
// System.out.println(i);
// 以下的 j 变量只要main方法未结束,就能用
int j =1;
for( ; j <= 10; j ++){
System.out.println(j);
}
//这里可以访问main方法中的 j 变量
System.out.println(j);
}
}
循环语句和条件判断语句嵌套【 for 和 if 】
public class Test{
public static void main(String[] args){
// 寻找 1-100 中的所有奇数
//第一种方法:从 1 开始,用循环,每次递增 2
for( int i = 1; i<=100 ; i += 2){
System.out.pintln(i);
}
// 第二种方法:从 1 开始,每次递增1,每次都判断是否可整除 2
for( int i = 1; i<= 100; i ++){
//判断 i 是否是奇数。“ & ”取余数,取模
// i % 2 == 0 偶数
// i % 2 == 1 奇数
// i % 2 != 0 奇数
if( i % 2 != 0 ){
System.out.pintln(i);
}
//以上两种方法,优先第一种,代码少,循环少,效率高
}
}
}
计算 1-100 内所有奇数的和,1+3+5+…+99
运算符 += 就是专门完成累加的
i += 1 —— i = i + 1
public class Test{
public static void maib(String[] args){
// 第一种:单用 for 循环
// 定义一个盒子
int sum = 0;
for(int i = 1; i <= 100; i += 2){
//此时输出的 i 都是奇数
// System.out.println(i);
//sum 存储的是最后求和的结果
sum += i;
}
// 以上的 for 循环结束之后,最终输出求和结果
System.out.println( "奇数的和:" + sum );
// 第二种:用 for 循环和 if 语句嵌套
// 归零
sum = 0;
for(int i = 1; i <= 100; i ++){
if( i % 2 != 0){
//此时的 i 都是奇数
//sum 存储的是最后求和的结果
sum += i; // 求和
}
}
// 以上的 for 循环结束之后,最终输出求和结果
System.out.println( "奇数的和:" + sum );
}
}
for 循环嵌套 for 循环【 for 和 for 】
内层循环的变量名和外层循环的变量名不可重名
public class Test{
public static void main(String[] args){
//不管循环体是什么代码,【循环体】都会执行 2 次
for(int i = 1; i <= 2; i ++){
System.out.println(i);
}
//写一个嵌套 for
//输出: 1 2 1 2 1 2 1 2
// 1 2 1 2 1 2 1 2
for( int i = 1; i < 5; i ++){
for(int j = 1; j < 3; j ++){ //输出:12 12
for(int k = 1; k < 3; k ++){ //输出:12
System.out.println(k);
}
}
}
}
}
public class Test{
public static void main(String[] args){
for(int i = 1; i < 5; i ++){
// 循环体的代码都会执行 4 遍
System.out.println("begin");
for(int j = 0; j < 1; j ++){ //循环2次,输出0
System.out.println(j);
}
System.out.println("end");
}
/* 输出结果
begin
0
end
begin
0
end
...
*/
}
}
引入 乘法表 前奏
public class Test{
public static void main(String[] args){
for(int i = 1 ; i <= 3; i ++){
for(int j = 1; j <= 3; j ++){
System.out.println(j):
}
}
/* 输出结果
1
2
3
1
2
3
...
*/
// 升级版
for(int i = 1; i <= 3; i ++){
for(int j = 1; j <=3; j ++){
System.out.println( i + "*" + j + "=" + (i*j));
}
}
/* 输出结果
1*1=1
1*2=2
1*3=3
2*1=2
2*2=4
2*3=6
3*1=3
3*2=6
3*3=9
*/
}
}
使用 for 循环输出 九九乘法表
注意有换行,呈现阶梯形状
public class Test{
public static void main(String[] args){
for(int i = 1; i <= 9; i ++){ // 外层循环9次,9行
for(int j = 1 ; j <= i; j ++){ //循环 i 次,列
System.out.print(i + "*" + j + "=" + (i*j));
System.out.print(" ");
}
System.out.print(\n);
}
}
}
需求:
编写 for 循环找出 1-100 中的所有素数
素数:即质数,仅可被 1 和自身整除,不可被其他数整除,13和17
啊
需求:
编写 for 循环找出 1-1000 中的所有素数
要求每 8 个换一行
while
- 语法结构
while ( 布尔表达式 ){
//循环体
} - while 循环的循环次数
while 循环的次数可能为 0 。【0 - N 次】 - 执行原理
a、先判断布尔表达式
b、若为 true ,执行循环体,再判断布尔表达式
c、若为 false ,循环结束
死循环
public class Test{
public static void main(String[] args){
// 死循环
while(true){
System.out.println("死循环");
}
// 程序报错,因为上面是死循环,下面的怎么都执行不到,就报错
/*
System.out.println(123);
*/
}
}
public class Test{
public static void main(String[] args){
int i =1;
int j =2;
while( j > i){
System.out.println("死循环");
}
//编译通过,虽然 2>1 是true,但是需要运算
//int i = 1; byte c = i / 2; — 会报错
System.out.println(123);
}
}
public class Test{
public static void main(String[] args){
while( 10 > 3 ){
System.out.println("死循环");
}
// 程序报错,因为上面是死循环,下面的怎么都执行不到,就报错
/*
System.out.println(123);
*/
}
}
使用 while 循环输出 1-10
public class Test{
public static void main(String[] args){
// 从小到大
int i = 1;
while( i < =10){
System.out.println(i);
i ++;
}
// 从大到小
int j = 10;
while( j >= 1){
System.out.println(j);
j --;
}
}
}
注意 i ++ 和 ++ i 的输出
public class Test{
public static void main(String[] args){
int j = 10;
while( j >= 1){
// 10 9 8 7 6 5 4 3 2 1
System.out.println(j --);
// 9 8 7 6 5 4 3 2 1 0
System.out.println(j );
}
int k = 10;
while( k >= 1){
// 9 8 7 6 5 4 3 2 1 0
System.out.println( -- k);
}
System.out.println( k); // 0
}
}
do…while()
- 语法结构
do {
// 循环体
} while ( 布尔表达式 ); - 执行原理
先执行循环体,再判断。所以至少都会执行一次循环体 - 执行次数
至少会执行一次。【 1 - N 次 】 - 注意事项
最后有个“分号”,不能忘了
public class Test{
public static void main(String[] args){
int i =1;
do{
System.out.println("我一直都在");
}while( i > 100);
// 输出 1-10
do{
// 1 2 3 4 5 6 7 8 9 10
System.out.println( i );
i ++;
} while ( i <= 10)
}
}
3、控制循环的语句
break
- break; 是关键字,翻译为“ 中断 / 折断 ”
- break + " ; " ,可以成为一个单独的Java语句
- break; 可以用在 switch 语句当中,用来终止语句执行
- break; 可以用在循环语句当中,用来终止循环的执行
- break; 终止的是当前所在的一次循环
- break; 语句用在 for,while,do…while 循环语句中,用来跳出循环,终止循环的执行。因为当程序循环到某个条件的时候,后续的循环没必要执行了,再执行也是耗费资源,所以终止循环,这样可以提高循环的执行效率
- 在默认情况下,break;终止的是离它最近的循环语句
break 是大哥,大哥说停就停,后面都不可以执行
public class Test{
public static void main(String[] args){
// 0 1 2 3 4
for(int i = 0; i <= 10; i ++){
if( i == 5){
break; //终止循环
}
System.out.println(i);
}
// 1 2 1 2 1 2
for(int i = 1; i <= 3; i ++){ //不管里面是啥都要循环3次
for(int j = 1; j <= 4; j ++){
if( j == 3){
break;
}
System.out.println(j);
}
}
}
}
以下用法比较少,给 for 循环命名,
public class Test{
public static void main(String[] args){
// 1 2 3 4 5 6
for1:for(int i = 1; i <= 5; i ++){
for2:for(int j = 1; j <= 10 ; j +=2){
if( j == 7){
break for1; // 终止 for1 循环
}
System.out.println( j );
}
}
}
}
continue
- continue;表示“ 继续 、下一个 ”
- continue + " ; " ,可以成为一个单独的Java语句。主要出现在循环语句中
- break 和 continue 的区别
a、break 表示循环不执行了,跳出循环,终止循环
b、continue 表示终止“本次”循环,直接进入下次循环 - 还有一种特殊写法
continue + 循环名称;【了解内容】
continue 是跟随 break 的小弟,但是没有那么厉害,只能终止当前一次循环,后面的循环照常执行
public class Test{
public static void main(String[] args){
// 1 2 4 5
for(int i =1; i <= 5; i ++){
if( i == 3){
// 只要这个语句执行,就只停止本次循环,直接进入下一次循环
continue;
}
System.out.println(i);
}
}
}
以下情况少用
public class Test{
public static void main(String[] args){
myFor:for(int i = 1; i < 5; i ++){
if( i == 2){
// 与 break 的不同之处,可后接循环名字
continue myFor;
}
Systtem.out.println( i );
}
}
}
八、方法初步
1、方法的好处
- 方法定义在类中,一个类中可以定义多个方法,位置随意
- 方法当中不可以再定义方法
- 方法体由Java语句构成,方法体内的代码执行是自上而下的
- 需要重复执行的功能,只是换了不同的数据,若不用方法就需要重复书写同样的代码。用方法就只需要向其传递不同的数据就行,最后只需要调用方法
- 比如计算两个数据的和,不使用方法就需要书写多遍Java语句
- 代码得到重复利用
public class Test{
// 类体
public static void main(String[] args){
//计算两个 int 类型数据的和,调用方法
sumInt(10 , 20);
sumInt(55 , 22);
sumInt(88 , 999);
}
// 单独定义一个方法
// 该方法完成计算两个 int 类型数据的和,并将结果输出
public static void sumInt(int a,int b){
int c = a + b;
System.out.println(c);
}
}
2、初识方法
- 方法的语法结构
【修饰符列表】 返回值类型 方法名(形式参数列表){
方法体;
} - 关于修饰符列表
①、可选项,不是必须的
②、方法修饰符列表有“static”,调用方法:
——类名.方法名(实际参数列表); - 关于返回值类型
①、方法执行之后大多数需要返回一个执行结果,执行结果可能是具体的数据,就是返回值
②、返回值类型就是方法执行之后将返回的值得类型
③、返回值类型可以是Java任意一数据类型,包括基本数据类型和引用数据类型
④、方法结束之后不返回执行结果,即返回值为空,则返回值类型为 void
⑤、返回值类型若不是 void,就必须要有返回值。怎么返回呢? “return 值;”其中“值”的类型必须与返回值类型一致
⑥、返回值类型若是 void,就不能写 “return 值;”,但是可以写 “return;”
⑦、只要编写带有 return 关键字的语句,当执行到这一句的时候,所在方法结束 - 方法名
①、方法名最好是动词
②、方法名需要见名知意
③、首字母小写,后面单词首字母大写 - 形式参数列表——形参
①、形参是局部变量
②、形参的个数:0 - N 个
③、多个形参之间用 “ 逗号 ” 隔开
④、形参中有决定性作用的是形参的数据类型
⑤、方法在被调用时,实际给方法传递的数据被称为实际参数列表,简称 “ 实参 ”
⑥、实参 和 形参必须满足——数量相同、类型对应相同
⑦、例如:
方法定义时
public static int sum( int a , String b ){ 这里是形参
}
方法调用时
sum( 1 , “aswecsd” ) 这是实参 - 方法体内自上而下执行,由大括号括起来
public class Test{
public static void main(String[] args) {
//调用方法
Test.sum(1,2);
//方法可以被重复利用
int x =10;
Test.sum(x , 2);
}
/*
自定义的方法,不是程序的入口
修饰符列表:public static
返回值类型:int
方法名:sum
形式参数列表:int a ,int b
方法体:求和并输出结果
*/
public static void sum(int a , int b){
System.out.println( a + "+" + b + "=" + (a + b));
}
}
3、方法体内执行顺序
- 方法体内执行顺序是自上而下的,上面的没有执行完绝对不会执行到下面的代码
- 方法的调用不一定是要在主方法当中,可以再其他方法中调用
- 只要是程序可以执行到的地方,都可以去调用其他方法
public class Test {
public static void sum(int a , int b){
System.out.println( a + "+" + b + "=" + (a + b));
Test.doSome();
}
//主方法,是程序的入口,从这里开始执行
public static void main(String[] args) {
//调用方法
Test.sum(1,2);
System.out.println("结束");
}
public static void doSome(){
System.out.println("Hello");
}
}
4、实参 和 形参
- 实参 和 形参必须满足——数量相同、类型对应相同
- 类型不同的时候要求能够相应的自动类型转换
public class Test {
public static void main(String[] args) {
//编译报错,实参和形参数量不同
//Test.sum();
//编译报错,实参和形参类型对应不同
//Test.sum(true,false);
//正确。存在自动类型转换:long a = 10; 有 int---->long
Test.sum(10 , 20);
//编译报错,实参和形参类型对应不同
//Test.sum(3.1 , 20);
Test.sum((long) 3.1, 20);
}
public static void sum(long a , long b){
System.out.println( a + "+" + b + "=" + (a + b));
}
}
5、方法的调用语法
方法的调用【有 static 修饰符】:
- 完整的调用语句——类名.方法名(实参列表);
- 有时候 “ 类名 . ” 可以省略——被调用方法与方法在同一个类中
- 可以省略。即同班同学
public class Test {
public static void main(String[] args) {
//调用方法,类名可省略
Test.m1();
m1();
//调用其他类中的方法不可省略类名。
//若省略,则默认在本类中寻找该方法
c.m3(); //c中的方法
m3(); //Test中的方法
}
public static void m1(){
System.out.println("Tset中的m1方法执行");
//完整的调用方法
Test.m3();
//省略的写法
m3();
//若调用其他类的同名方法
c.m3();
}
public static void m3(){
System.out.println("Tset中的m3方法执行");
}
}
class c{
public static void m3(){
System.out.println("c1中的m3方法执行");
}
}
判断以下代码的执行输出结果
public class Test {
public static void main(String[] args) {
System.out.println("草莓1");
m1();
System.out.println("草莓2");
}
public static void m1(){
System.out.println("西瓜1");
m2();
System.out.println("西瓜2");
}
public static void m2(){
System.out.println("荔枝1");
System.out.println("荔枝2");
}
}
6、返回值类型不是 void 的时候
方法的返回值类型不是 void 的时候:
- 当返回值不为空时,必须执行 “ return 值;” 的语句来完成值得返回。若没有 “ return 值;” 就会报错, “ return;” 都不行
- 返回的值的类型必须和返回值类型一致
- 方法调用的时候可以选的接收被调用方法的执行结果,也可以选择不接收
public class Test {
public static void main(String[] args) {
//调用方法,但是未接受方法执行结果
divide(10,3);
//接受方法执行结果。可以采用变量接收
//变量的数据类型需要和方法的返回值类型一致,或者可以自动类型转换
int i = divide(10,3);
long l = divide(10,3);
System.out.println(divide(10,3));
}
//定义一个方法,计算两个int类型数据的商,要求把计算结果返回给调用者
public static int divide(int a ,int b ){
int c = a / b;
return c;
}
}
7、深入 return 语句:
- 带有 return 关键字的 Java 语句只要执行,所在的方法结束
- 在 “同一个作用域” 中,return 语句后面不可写任何代码,因为执行不到
public class Test{
public static void main(String[] args){
//调用方法,方法名后需要括号。没括号就以为是 变量m
int result = m();
System.out.println( result );
System.out.println( m() );
}
/*
以下编译报错。缺少返回语句
程序只编译不运行,编译器不认为 “return 1” 会百分百执行
public static int m(){
int a = 10;
if(a > 3){
return 1;
}
}
*/
//以下语句能保证 return 语句肯定会执行到
public static int m(){
int a = 10;
if(a > 3){
return 1;
}else{
return 0;
}
}
//上面的方法也可以这样写。
//若执行了 if 语句,方法就结束,因为有 return 1;
//若不执行 if 语句,就执行了 return 0;方法也结束。
public static int m1(){
int a = 10;
if(a > 3){
return 1;
}
return 0;
}
//上面的方法也可以这样写。
public static int m2(){
return 10 > 3 ? 1 : 0;
}
}
“同一个作用域” 中,return 语句后面不可写任何代码
public static int m3(){
int a = 10;
if(a > 3){
return 1;
//编译报错,因为该句永远执行不到
//System.out.println("草莓");
}
//编译通过
System.out.println("草莓");
return 0;
}
在 返回值为空的方法中使用 return 语句。
作用: “ return;” 语句是为了结束该方法的执行
public class Test {
public static void main(String[] args) {
}
// 编译报错。对于返回值为空的方法,无法返回值
/*
public static void m1( ) {
return 1;
}
*/
//编译通过
public static void m1( ) {
return ;
}
}
public class Test {
public static void main(String[] args) {
m1();
}
//在返回值为空的方法中使用 return 语句
public static void m1( ) {
for(int i = 1 ; i <= 10 ; i ++){
if(i == 5){
return;
}
System.out.println("i--->" + i);
}
System.out.println("hello");
}
}
输出结果:
public class Test {
public static void main(String[] args) {
m1();
}
public static void m1( ) {
for(int i = 1 ; i <= 10 ; i ++){
if(i == 5){
//return; //终止的是 m1() 方法
break; //终止的是 for 循环
}
System.out.println("i--->" + i);
}
System.out.println("hello");
}
}
输出结果:
public class Test {
public static void main(String[] args) {
m1();
for(int j = 10; j > 0; j --){
if(j == 6){
return;
}
System.out.println("草莓--->" + j);
}
System.out.println("hello");
}
public static void m1( ) {
for(int i = 1 ; i <= 10 ; i ++){
if(i == 5){
//return; //终止的是 m1() 方法
break; //终止的是 for 循环
}
System.out.println("i--->" + i);
}
System.out.println("hello");
}
}
输出结果:
8、方法执行时的内存分配
- 方法只定义,不调用,是不会执行的,并且在JVM中也不会给该方法分配 “ 运行所属 ” 的内存空间。只有在调用这个方法的是很,才会动态的给这个方法分配所属的内存空间
- 在 JVM 中有三块主要的内存空间:
①、方法区内存
②、栈内存
③、堆内存 - 关于 “ 栈 ” 数据结构:
①、栈:Stack,是一种数据结构
②、数据结构反映的是数据的存储形态
③、数据结构是独立的学科
④、需要精通:数据结构+算法
⑤、常用的数据结构:数组、队列、栈、链表、二叉树、哈希表 / 散列表… - 方法代码片段存在哪里?执行过程中的内存在哪里分配?
①、方法代码片属于 .class字节码文件的一部分,字节码文件在类加载的时候,将其放到了方法区当中,所以JVM中的三块主要内存空间中方法区最先由数据,存放了代码片段
②、代码片段虽然在方法区内存当中只有一部分,但是可以被重复调用 - 方法在调用的瞬间,会给该方法分配内存空间,会在栈中发送压栈动作。方法执行结束之后,给该方法分配的内存空间全部释放,此时发送弹栈动作
①、压栈:给方法分配内存
②、弹栈:释放该方法的内存空间 - 局部变量 在 “ 方法体 ” 中声明。运行阶段内存在栈中分配
9、代码运行时内存分配分析
- 方法区存的是字节码文件。
- 方法调用时,参数传递的时候,实际传递的是变量中保存的字面值,而不是变量本身
- 画图时,必须遵循 “ 方法自上而下的顺序依次执行 ” 这个原则
- 代码编译期不会执行任何计算,JVM执行时计算
- 栈结构遵循 先进后出,后进先出 的规则
- 栈内存主要存储的是局部变量
- 栈帧永远在栈顶,栈顶元素永远处于活跃状态,其他元素静止
详见方法内存分析
10、画图练习
- 分析输出结果
- 程序执行到哪一步,画图时就体现到哪一步
public class Test{
public static void main(String[] args){
int i =10;
m(i);
System.out.println("main--->" + i); // 10
}
public static void m(){
i ++;
System.out.println("m--->" + i); // 11
}
}
11、方法重置
1、以下代码不使用方法重载,缺点
public class Test{
//入口
public static void main(String[] args){
// 调用方法
System.out.println(sumInt(1 , 2));
System.out.println(sumDouble(1.6 , 2.8));
System.out.println(sumLong(5L , 10L));
}
//定义方法,计算两个 int 数据的和
public static int sumInt(int a, int b){
return a + b;
}
//定义方法,计算两个 double 数据的和
public static double sumDouble(double a, double b){
return a + b;
}
//定义方法,计算两个 long 数据的和
public static long sumLong(long a, long b){
return a + b;
}
}
缺点:
- 三个方法的功能虽然都不同,但是很相似,都是求和。三个功能相似的方法,分别起了三个不同的名字,这使得在调用时要记多个方法名,很不方便
- 代码不美观
2、以下代码使用方法重载,优点
public class Test{
public static void main(String[] args){
// 调用方法的时候就像在用一个方法。但其实参数的类型不同,对应调用的方法不同
//此时区分方法不再依靠方法名,而是依靠实际参数列表的数据类型
System.out.println(sum(1 , 2));
System.out.println(sum(1.6 , 2.8));
System.out.println(sum(5L , 10L));
}
public static int sum(int a, int b){
System.out.println("int的求和");
return a + b;
}
public static double sum(double a, double b){
System.out.println("double的求和");
return a + b;
}
public static long sum(long a, long b){
System.out.println("long的求和");
return a + b;
}
}
输出结果:
优点:
- 调用方法的时候比较方便
- 代码美观
- 前提是功能相似的情况下,使用方法重载。若功能不同,方法名还是需要不同
3、方法重载 overload
- 方法重载:overload
- 什么时候用:
a、功能相似的时候,让方法名相同。
b、若功能不相似,方法名需要不同 - 什么条件构成方法重载:
、在同一个类中
、方法名相同
、参数列表不同——数量不同,顺序不同,类型不同 - 方法重载和什么有关系,和什么没关系:
、方法重载和方法名+参数列表无关
、方法重载和返回值类型无关
、方法重载和修饰符列表无关
public class Test{
public static void main(String[] args){
m();
m(1);
m1( 2 , 3.0);
m1( 3.2 , 10);
m2( 3 );
m2( 4.9 ):
}
//以下两个方法构成重载
public static void m(){}
public static void m(int a){}
//以下两个方法构成重载
public static void m1(int a , double b){}
public static void m1(double a ,int b){}
//以下两个方法构成重载
public static void m2(int x){}
public static void m2(double y){}
}
以下是反面举证
public class Test{
public static void main(String[] args){
}
//以下两个方法不是重载,是发送了方法重复
public static void method(int a , double b){}
public static void method(int a , double b){}
//以下两个方法不是重载
public static void x(){}
public static int x(){
return 1;
}
//以下两个方法不是重载
void y(){}
public static void y(){}
}
九、递归问题
认识递归
- 什么是递归?递归就是方法自己调用自己
- 递归很耗费栈内存,递归算法能不用尽量不用
- 以下程序运行时发生错误【不是异常,是错误Error】
java.lang.StackOverflowError
栈内存溢出错误
错误无法挽回,只有一个结果,就是 JVM 停止工作 - 递归必须有结束条件,没有结束条件一定会发生栈内存溢出错误
- 递归即使有了结束条件,即使条件是正确的,也可能会发生栈内存溢出错误,因为递归的太深了
详见文章Java方法递归
十、对象与类
面向过程和面向对象的区别
- 面向过程:
- 主要关注点是:实现的具体过程,因果关系。[集成显卡的开发思路]
- 优点:对于业务逻辑比较简单的程序,可以达到快速开发,前期投入成本较低。
- 缺点:采用面向过程的方式开发很难解决非常复杂的业务逻辑,另外面向过程的方式导致软件元素之间的**“耦合度”非常高,只要其中一环出问题,整个系统受到影响,导致最终的软件“扩展力”**差。另外,由于没有独立体的概念,所以无法达到组件复用。
- 面向对象:
- 主要关注点是:主要关注对象[独立体]能完成哪些功能。[独立显卡的开发思路]
- 优点:耦合度低,扩展力强。更容易解决现实世界当中更复杂的业务逻辑。组件复用性强。
- 缺点:前期投入成本较高,需要进行独立体的抽取,大量的系统分析设计。
现在出现的一些新的编程语言多数都是面向对象的。人在认识现实世界的时候以面向对象的方式。面向对象更符合人的思维方式。
面向对象的三大特征:封装,继承,多态
采用面向对象的方式开发一个软件,生命周期当中:[整个生命周期中贯穿使用oo面向对象方式]
面向对象的分析: OOA
面向对象的设计: OOD
面向对象的编程: OOP
类和对象的概念
★什么是类?
类在现实世界当中是不存在的,是一个模板,是一个概念。是人类大脑思考抽象的结果。
类代表了一类事物。
在现实世界当中,对象A与对象B之间具有共同特征,进行抽象总结出一个模板,这个模板被称为类
.★什么是对象?
对象是实际存在的个体。现实世界当中实际存在.
⭐描述一下整个软件开发的过程:
程序员先观察现实世界,.从现实生活当中寻找对象
寻找了N多个对象之后,发现所有的对象都有共同特征
程序员在大脑中形成了一个模板【类】
Java程序员可以通过java代码来表述一个类
Java程序中有了类的定义,然后通过类就可以创建对象
有了对象之后,可以让对象直接协作起来形成一个系统。
*类-- [实例化] ->对象
★对象又被称为实例 / instance
★对象-- [抽象] -->类