Java 中的基本数据类型主要包括以下7种:
- byte:字节型,占用 1 字节,范围-128 到 127。
- char:字符型,占用 2 字节,范围 0 到 65535。
- short:短整型,占用 2 字节,范围-32768 到 32767。
- int:整型,占用 4 字节,范围-2147483648 到 2147483647。
- long:长整型,占用 8 字节,范围-9223372036854775808 到 9223372036854775807。
- float:单精度浮点型,占用 4 字节,有效位可以达到 6-7 位。精确到小数点后 6~7 位。
- double:双精度浮点型,占用 8 字节,有效位可以达到 15 位。精确到小数点后 15~16 位。
这些类型在内存中的占用大小是固定的,但是它们可以存储的值的大小或者精度是不同的。例如,byte、short、int、long 类型可以存储整数,但是它们存储的最大值和最小值是不同的;float 和 double 可以存储浮点数,但是它们的精度(小数点后几位)是不同的。
按照精度从大到小排列Java中这些基本数据类型,主要针对的是这些类型所能表示的数值范围或精确度,我们按照数值范围和精确度来排序:
- double:双精度浮点型,精度最高,可以表示的数非常大或非常小,精确到小数点后15~16位。
- float:单精度浮点型,精度次之,可以表示的数范围较大,精确到小数点后6~7位。
- long:长整型,可以表示的整数范围很大,从-9223372036854775808到9223372036854775807。
- int:整型,可以表示的整数范围较大,从-2147483648到2147483647。
- short:短整型,表示的整数范围较小,从-32768到32767。
- byte:字节型,表示的整数范围最小,从-128到127。
- char:字符型,虽然它是用来表示Unicode字符的,不过由于它在底层是以一个无符号的16位整数存储,理论上可以视作从0到65535的范围,但是它主要用于表示字符而不是数值,所以在这个列表中的位置比较特殊。如果只从数值的角度考虑,则可以考虑它大致位于
short
和int
之间,但实际用途有所不同。
这里重点是基于能表示的数值范围和精确度进行排序。需要注意的是,精确度主要是指浮点数(float和double)的精确度,而对于整数类型(byte, short, int, long)则主要考虑的是它们能表示的数值范围。而char
主要用于表示字符,但在某些语境下也可能被用作数值处理。
类型转换
在Java编程中,类型转换是一个重要的概念,不同的数据类型之间的转换可以分为隐式转换(自动转换)和显式转换(强制转换)。以下是对Java中不同类型转换的详细解析及需要注意的问题。
一、类型转换的概述
类型转换可以分为以下几种:
- 隐式转换(自动类型提升)
- 显式转换(强制类型转换)
- 对象类型转换
二、隐式转换
隐式转换是指无需显式指定,编译器会自动完成的数据类型转换。通常发生在小容量类型到大容量类型的转换过程中。
转换规则:
Java中的数据类型按容量大小排列:
byte -> short -> int -> long -> float -> double
示例:
int i = 100;
long l = i; // int 自动提升为 long
float f = l; // long 自动提升为 float
在上面的代码中,int
自动提升为 long
,long
自动提升为 float
,这是因为 long
和 float
分别比 int
和 long
表示的数值范围更广。
三、显式转换
显式转换需要通过强制类型转换来实现,通常用于大容量类型转换为小容量类型,这可能会有数据丢失的风险。
转换规则:
语法:(目标类型) 值
示例:
double d = 9.78;
int i = (int) d; // 强制转换 double 为 int
System.out.println(i); // 输出: 9
上面的代码通过 (int)
将 double
显式转换为 int
,小数部分被截断,因此输出为9。
注意事项:
- 数据丢失:当进行显式转换时,如果目标类型不能表示源类型的数值可能会导致数据丢失。
- 范围超出:显式转换可能导致溢出问题。
四、对象类型转换
对象类型转换也称为“类型转换检查”,尤其是在涉及继承关系和多态性的情况下。
向上转型(Upcasting)
将子类对象转换为父类类型,这是隐式的,无需强制转换语法。
示例:
class Animal {}
class Dog extends Animal {}
Animal a = new Dog(); // 自动进行向上转型
向下转型(Downcasting)
将父类对象转换为子类类型,这需要显式转换。
示例:
Animal a = new Dog();
Dog d = (Dog) a; // 强制进行向下转型
// 注意:仅当 'a' 实际上是一个 'Dog' 实例时,这种转换才是安全的。
注意事项:
- ClassCastException:如果试图将父类对象转换为一个不正确的子类类型,会抛出
ClassCastException
。 instanceof
操作符:在进行向下转型之前,使用instanceof
检查可以避免异常。
示例:
Animal a = new Animal();
if (a instanceof Dog) {
Dog d = (Dog) a;
} else {
System.out.println("a 不是 Dog 类型");
}
五、基本类型与包装类之间的转换
Java提供了自动装箱(Autoboxing)和自动拆箱(Unboxing)特性,这使得基本数据类型和其对应的包装类之间的转换更加方便。
装箱(Autoboxing)
将基本数据类型转换为对应的包装类对象。
示例:
int i = 5;
Integer intObj = i; // 自动装箱
拆箱(Unboxing)
将包装类对象转换为对应的基本数据类型。
示例:
Integer intObj = 10;
int i = intObj; // 自动拆箱
六、小结
自动类型提升(隐式转换)
- 在进行数学运算时,例如加法运算,较小的数据类型会自动提升为较大的数据类型。
- 常用于从较低精度转换为较高精度,从
byte
到int
,再到long
,再到float
,直到double
。
强制类型转换(显式转换)
- 只在需要降低精度时使用,例如从
double
转int
,需要使用(int)
的形式。 - 可能导致数据截断或精度丢失。
对象类型转换
- 向上转型(隐式)
- 向下转型(显式),需谨慎使用并确保安全。
包装类与基本数据类型转换
- 自动装箱与拆箱方便了基本数据类型和包装类对象之间的转换。
熟悉这些类型转换的规则和注意事项是编写健壮且高效Java代码的基础。希望这些详细解释能够帮助你更好地理解Java中的类型转换。
例子:
public class forceConvert02{
public static void main(String[] args){
byte a = 10;
char c = 'g';
float f = 1.2f;
double d = a + c + f ;
short s = 100;
int c1 = s + a;
String str1 = a + "";
String str2 = c + "";
String str3 = f + "";
String str4 = d + "";
System.out.println(str1 + str2 + str3 + str4);
String s5 = "123"; //字符串可以符合对应的类型
int i = Integer.parseInt(s5);
short i2 = Short.parseShort(s5);
byte i3 = Byte.parseByte(s5);
long i4 = Long.parseLong(s5);
float i5 = Float.parseFloat(s5);
double i6 = Double.parseDouble(s5);
boolean i7 = Boolean.parseBoolean("true");
System.out.println("===========================");
System.out.println(i);
System.out.println(i2);
System.out.println(i3);
System.out.println(i4);
System.out.println(i5);
System.out.println(i6);
System.out.println(i7);
System.out.println(s5.charAt(2));
}
}
运行结果:
10g1.2114.19999694824219
===========================
123
123
123
123
123.0
123.0
true
3
运算符
Java 中的常用算术运算符包括以下几种:
-
加号
+
:用于两个数值的加法运算,或者用于字符串的连接操作。 -
减号
-
:用于两个数值的减法运算。 -
乘号
*
:用于两个数值的乘法运算。 -
除号
/
:用于两个数值的除法运算。如果两个操作数都是整数,则执行整数除法,结果为商的整数部分;如果至少有一个操作数为浮点数,则执行浮点除法。 -
取模
%
:俗称取余,用于两个数值的取模运算,结果为两数相除后的余数。 -
自增
++
:将变量的值增加 1,分为前缀形式(例如++i
,先进行自增运算,再返回运算后的值)与后缀形式(例如i++
,先返回当前值,然后再进行自增运算)。 -
自减
--
:将变量的值减少 1,也分为前缀形式(例如--i
)与后缀形式(例如i--
)。
请注意,使用这些运算符时可能需要考虑运算的类型转换和溢出等问题。例如,当两个整数相除时,如果你希望得到浮点数结果,至少需要有一个操作数进行显式或隐式的类型转换为浮点数。
++i
和 i++
,以及 --i
和 i--
都是 Java 中的自增和自减运算符,主要的区别在于它们在表达式中的值和它们对原变量的修改时间不同。
-
++i(前缀自增):首先,将 i 的值加 1,然后返回加 1 后的 i。这就意味着,如果我们在一个表达式中使用
++i
,那么在这个表达式中,i 的值都是自增后的值。 -
i++(后缀自增):首先,返回当前的 i,然后再将 i 的值加 1。这就意味着,如果我们在一个表达式中使用
i++
,那么在这个表达式中,i 的值都是自增前的值。
同样,
-
–i(前缀自减):首先,将 i 的值减 1,然后返回减 1 后的 i。这就意味着,如果我们在一个表达式中使用
--i
,那么在这个表达式中,i 的值都是自减后的值。 -
i–(后缀自减):首先,返回当前的 i,然后再将 i 的值减 1。这就意味着,如果我们在一个表达式中使用
i--
,那么在这个表达式中,i 的值都是自减前的值。
例如:
int i = 10;
System.out.println(++i); // 输出11, i的值现在是11
i = 10; // 重新赋值
System.out.println(i++); // 输出10,但是 i 的值现在是11
同样,对于自减运算符:
int i = 10;
System.out.println(--i); // 输出9,i的值现在是9
i = 10; // 重新赋值
System.out.println(i--); // 输出10,但是i的值现在是9
所以,选择使用哪种形式,前缀还是后缀,取决于你是希望在表达式中使用的是变量改变前的值,还是改变后的值。
取模运算,也叫做取余运算,是一种在数学和计算机科学中常见的运算。优先定义在整数集上,是一种求余数的操作。在Java中,取模运算符为 %
。
取模运算的基本公式为:
a % b = a − F l o o r ( a / b ) ∗ b a \% b = a - Floor(a / b) * b a%b=a−Floor(a/b)∗b
其中,Floor
表示向下取整,a
表示被除数,b
表示除数。
例如:
13 % 5 = 13 - Floor(13 / 5) * 5 = 13 - 2 * 5 = 3
。因此,13 除以 5 的余数是3。
在特定的数学和计算机科学应用中,取模运算有很多用途。例如,在哈希函数或者散列函数中,取模运算常用于将大的数值范围映射到小的数值范围(例:数组的索引)。同样,它也在循环队列和循环数组中发挥着重要的作用,可以简化在数组末尾和开头之间的过渡。
举例:
[root@master ~/java/javacode]# vim ArithmeticOperator.java
public class ArithmeticOperator{
public static void main(String[] args){
System.out.println(10 / 4);
double a = 10;
System.out.println(a / 4);
//默认按照最大精度进行计算
System.out.println(10.0 / 4);
//算术
//单独情况下i++ 与++i是一样的
int i = 10;
//i++; // ==> 11
//++i; // ==> 11
System.out.println(i);
//取模:a % b ==> a - a / b * b
System.out.println(10 % 3); // 1
System.out.println(10 % -3); // 1
System.out.println(-10 % 3); // -1
/*
作为表达式使用:
前++:先自增,后赋值
后++:先赋值,后自增
*/
int j = 10;
//int f = j++; //f=j;j=j+1 f=10 j=11
int f = ++j; //j=j+1;f=j f=11 j=11
System.out.println("f="+f+"\tj="+j);
}
}
在Java中,逻辑运算符用于连接两个或多个布尔表达式,其结果也是布尔值(true
或 false
)。以下是Java中的几种基本逻辑运算符及其规则:
-
&&
- 逻辑与(AND)运算符:- 如果两个操作数都为
true
,结果为true
。 - 如果任何一个操作数为
false
,结果为false
。 &&
是短路运算符,如果第一个操作数为false
,它将不会评估第二个操作数。
- 如果两个操作数都为
-
||
- 逻辑或(OR)运算符:- 如果两个操作数中任意一个为
true
,结果为true
。 - 如果两个操作数都为
false
,结果为false
。 ||
也是短路运算符,如果第一个操作数为true
,它将不会评估第二个操作数。
- 如果两个操作数中任意一个为
-
!
- 逻辑非(NOT)运算符:- 如果操作数为
true
,结果为false
。 - 如果操作数为
false
,结果为true
。
- 如果操作数为
以下是一些逻辑运算符的使用示例:
boolean a = true;
boolean b = false;
// 逻辑与
boolean resultAnd = a && b; // 结果为 false,因为 b 是 false
// 逻辑或
boolean resultOr = a || b; // 结果为 true,因为 a 是 true
// 逻辑非
boolean resultNot = !a; // 结果为 false,因为 a 的取反是 false
使用逻辑运算符时需要特别注意操作符的短路行为,这在编写条件语句时非常有用,可以避免不必要的计算,例如,避免在条件判断中调用一个可能导致异常的方法:
if (obj != null && obj.someMethod()) {
// 只有当 obj 不为 null 时才会调用 someMethod 方法.
}
在上面的代码中,如果 obj
为 null
,由于 &&
的短路特性,将不会调用 someMethod
方法。这样可以有效避免 NullPointerException
的发生。
好的,我将通过例子来详细说明逻辑与(&
)与短路与(&&
),以及逻辑或(|
)与短路或(||
)之间的区别。
逻辑与&
和短路与&&
的比较
首先定义两个方法,这些方法会在被调用时打印一条信息,并返回布尔值:
public class LogicalDemo {
public static void main(String[] args) {
boolean result;
boolean a, b;
a = false;
b = true;
System.out.println("逻辑与 & 的操作:");
result = testA(a) & testB(b);
// 在这里,无论testA()的结果如何,testB()都将被执行
System.out.println("\n短路与 && 的操作:");
result = testA(a) && testB(b);
// 在这里,如果testA()返回false,testB()不会被执行
}
public static boolean testA(boolean a) {
System.out.println("testA 方法被调用,返回:" + a);
return a;
}
public static boolean testB(boolean b) {
System.out.println("testB 方法被调用,返回:" + b);
return b;
}
}
输出:
逻辑与 & 的操作:
testA 方法被调用,返回:false
testB 方法被调用,返回:true
短路与 && 的操作:
testA 方法被调用,返回:false
逻辑或|
和短路或||
的比较
类似地,我们可以使用同样的方法来展示逻辑或和短路或的区别:
a = true;
b = false;
System.out.println("逻辑或 | 的操作:");
result = testA(a) | testB(b);
// 在这里,无论testA()的结果如何,testB()都将被执行
System.out.println("\n短路或 || 的操作:");
result = testA(a) || testB(b);
// 在这里,如果testA()返回true,testB()不会被执行
输出:
逻辑或 | 的操作:
testA 方法被调用,返回:true
testB 方法被调用,返回:false
短路或 || 的操作:
testA 方法被调用,返回:true
在上面的示例中,可以看到:
- 当使用逻辑与
&
时,不论testA()
的结果如何,testB()
都会被执行。 - 当使用短路与
&&
时,由于testA()
返回false
,testB()
不会被执行,因为&&
操作符已经确定整个表达式的结果必定是false
。 - 当使用逻辑或
|
时,不论testA()
的结果如何,testB()
都会被执行。 - 当使用短路或
||
时,由于testA()
返回true
,testB()
不会被执行,因为||
操作符已经确定整个表达式的结果必定是true
。
从这些例子中可以明显看出短路行为对程序执行流程的影响。使用短路逻辑与&&
和短路逻辑或||
通常可以提高效率,特别是当第二个操作数的计算代价高昂或者具有潜在副作用时(比如修改状态或进行I/O操作)。
例子1:
public class RelationalOperator{
public static void main(String[] args){
// int a = 1;
// int b = 3;
// boolean f = b < 3;
// System.out.println(f);
//demo01:
boolean a = false;
boolean b = true;
boolean result , result2;
//logic
result = test1(a) && test2(b) ;
result2 = test1(a) & test2(b) ;
int a1 = 1;
int b1 = 10;
//短路与&&
if ( a1 < 1 && b1++ < 90){
System.out.println("ok");
}
System.out.println("a1="+a1+"\tb1="+b1);
//逻辑与&
if ( a1 < 1 & b1++ < 90){
System.out.println("ok");
}
System.out.println("a1="+a1+"\tb1="+b1);
}
//定义一个方法
public static boolean test1(boolean a){
System.out.println("返回test1==>:"+a);
return a;
}
public static boolean test2(boolean b){
System.out.println("返回test2==>:"+b);
return b;
}
}
运行结果:
[root@master ~/java/javacode]# javac RelationalOperator.java &&java RelationalOperator
返回test1==>:false
返回test1==>:false
返回test2==>:true
a1=1 b1=10
a1=1 b1=11
例子2:
[root@master ~/java/javacode]# vim RelationalOperator03.java
public class RelationalOperator03{
public static void main(String[] args){
int a = 100;
int b = 10;
//逻辑非(NOT)
System.out.println(!(a<10)); // T
System.out.println(!(a>10)); // F
//异或
System.out.println((a < 10)^(b <=10));
}
}
结果:
[root@master ~/java/javacode]# javac RelationalOperator03.java && java RelationalOperator03
true
false
true
例子3:
public class RelationalOperator03{
public static void main(String[] args){
int a = 100;
int b = 10;
if (++a==101 && ++b ==11){
a =120;
}
System.out.println("a="+a+"\tb="+b);
}
}
结果:
a=120 b=11
例子4:
public class RelationalOperator03{
public static void main(String[] args){
int a = 100;
int b = 10;
if (a++==101 & ++b ==11){
a =120;
}
System.out.println("a="+a+"\tb="+b);
}
}
结果:
a=101 b=11
例子5:
public class RelationalOperator03{
public static void main(String[] args){
int a = 100;
int b = 10;
if (a++==100 || ++b ==10){
a =120;
}
System.out.println("a="+a+"\tb="+b);
}
}
结果:
a=120 b=10
例子6:
public class RelationalOperator03{
public static void main(String[] args){
int a = 100;
int b = 10;
if (a++==100 | ++b ==10){
a =120;
}
System.out.println("a="+a+"\tb="+b);
}
}
结果:
a=120 b=11
例子7:
public class RelationalOperator03{
public static void main(String[] args){
boolean x =true;
boolean y = false;
short z = 46;
if ((y = true) && (z++==46)) z++;
if ((x = false) || (++z==49)) z++;
System.out.println("x="+x+"\ty="+y+"\tz="+z);
}
}
结果:
x=false y=true z=50
三元运算符
Java 中的三元运算符(ternary operator)是唯一的一个条件运算符,它包含三个操作数,可以用于代替简单的 if-else 语句,以实现代码简化。它的一般形式如下:
variable = Expression1 ? Expression2 : Expression3;
这里的工作原理解释如下:
Expression1
:这是一个布尔表达式,决定了接下来的计算路径,如果表达式为true
,将执行Expression2
,否则执行Expression3
。Expression2
:这是Expression1
为true
时被赋值给variable
的值。Expression3
:这是Expression1
为false
时被赋值给variable
的值。
使用三元运算符时需要特别注意以下几点:
-
表达式的类型必须是兼容的:
Expression2
和Expression3
应该返回兼容类型的值,或可自动转换为变量类型。否则,可能导致编译错误。 -
三元运算符可以嵌套:但为了阅读和维护的便利性,应尽量避免复杂的嵌套,因为它会使代码难以阅读。
-
三元运算符是右结合的:意味着嵌套的三元运算符会从右向左进行求值。
-
三元运算符无法替代所有的 if-else 逻辑:仅在条件下根据不同的真值选择不同的值时使用,不应用于复杂的程序逻辑或执行多条语句。
下面是一个简单的例子1:
int a = 5;
int b = 10;
int max = (a > b) ? a : b; // 如果a大于b,max值为a,否则为b
例子2:
public class TernaryOperator{
public static void main(String[] args){
int a = 10 , b = 99;
int result = a > b ? a++ : b--;//b--:先进行赋值:result=b ==> 99;在进行b--操作:b=b-1 ==> 98;
System.out.println("result="+result+"\ta="+a+"\tb="+b);
}
}
运行结果:
result=99 a=10 b=98
例子3:
public class TernaryOperator{
public static void main(String[] args){
int a = 10 , b = 99;
int result = a > b ? a++ : --b; //--b:先计算b=b-1 ==>98;在进行赋值:result=b ==> 98;
System.out.println("result="+result+"\ta="+a+"\tb="+b);
}
}
运行结果:
result=98 a=10 b=98
例子4:
public class TernaryOperator{
public static void main(String[] args){
int a = 10 , b = 99;
int result = a < b ? a++ : --b;
System.out.println("result="+result+"\ta="+a+"\tb="+b);
}
}
运行结果:
result=10 a=11 b=99
例子5:
public class TernaryOperator{
public static void main(String[] args){
int a = 10 , b = 99;
int result = a < b ? ++a : b--;
System.out.println("result="+result+"\ta="+a+"\tb="+b);
}
}
运行结果:
result=11 a=11 b=99
在使用时,不仅要考量代码的简洁性,还要保持代码的可读性和后期维护的方便性。
特性:三元运算符数据类型强转
例子:
public class TernaryOperator02{
public static void main(String[] args){
int a = 10 , b = 99;
double result = a < b ? 1.1 : b; //double result = a;
System.out.println("result="+result+"\ta="+a+"\tb="+b);
}
}
运行结果:
result=1.1 a=10 b=99
三元运算符作业
比较3个数,并返回最大值:
解题思路:
- n1 与 n2 做比较得出其中较大的值;
- n3 与 n2/n1中的较大值比较,返回较大值
public class TernaryOperatorExercise{
public static void main(String[] args){
int a = 10 , b = 123 , c = 321;
//1. n1 与 n2 做比较得出其中较大的值;
int result = a > b ? a : b ;
//2. n3 与 n2/n1中的较大值比较,返回较大值
int result2 = c > result ? c :result;
System.out.println("result="+result+"\nresult2="+result2);
}
}
运行结果:
result=123
result2=321
用一条语句解决:
public class TernaryOperatorExercise{
public static void main(String[] args){
int a = 10 , b = 123 , c = 321;
int result2 = c > (a > b ? a : b) ?
c :(a > b ? a : b);
System.out.println("result2="+result2);
}
}
运算优先符
在程序设计中,运算符优先级决定了表达式中各个运算符的运算顺序。了解和掌握每种运算符的优先级是非常重要的,因为它决定了如何对表达式进行求值。下面是一些常见编程语言(如C/C++、Java、Python等)中运算符的优先级列表,从**高到低排序
**(使用“R-->L
”表示从右向左
运算,使用“L->R
”表示从左向右
运算)
下面是更新后的表格:
优先级 | 类别 | 运算符 | 描述 | 运算方向 |
---|---|---|---|---|
1 | 括号 | () | 表达式内的括号优先计算 | L–>R |
2 | 成员访问 | . 、-> | 对象和指针成员访问 | L–>R |
3 | 单目运算符 | ! 、~ 、+ (正)、- (负)、++ (前置)、-- (前置)、* (解引用)、& (取地址) | 单个操作数的运算符 | R–>L |
4 | 类型转换 | 类型转换操作 | 如 (int) , (double) 等 | L–>R |
5 | 乘除模 | * 、/ 、% | 乘法、除法、取模运算 | L–>R |
6 | 加减法 | + 、- | 加法、减法 | L–>R |
7 | 位移运算 | << 、>> | 左右位移 | L–>R |
8 | 关系比较 | < 、> 、<= 、>= | 大小比较 | L–>R |
9 | 相等比较 | == 、!= | 等于、不等于比较 | L–>R |
10 | 位运算 | & 、^ 、` | ` | 按位与、异或、或 |
11 | 逻辑运算 | && 、` | ` | |
12 | 条件运算符 | ?: | 三元条件运算 | R->L |
13 | 赋值运算符 | = 、+= 、-= 、*= 、/= 、%= 、<<= 、>>= 、&= 、^= 、` | =` | 赋值及其复合形式 |
14 | 逗号 | , | 表达式分隔符 | L->R |
每个运算符的运算方向决定了如果有多个同级运算符出现在一个表达式中,它们是如何顺序执行的。
命名规则
在Java编程语言中,标识符(Identifier)是用于标识变量、函数、类等实体的名称。命名规则和规范如下:
-
合法字符
- 标识符只能包含字母(A-Z, a-z)、数字(0-9)、下划线(_)和美元符号($)。
- 标识符不能以数字开头。
-
区分大小写
- Java是区分大小写的语言,因此
MyVariable
和myvariable
是两个不同的标识符。
- Java是区分大小写的语言,因此
-
长度限制
- 标识符的长度不受限制,但过长的标识符会影响代码的可读性。
-
关键字和保留字
- 标识符不能使用Java的关键字(如
class
,public
,void
, 等)和保留字。 关键字
:
保留字
:
- 标识符不能使用Java的关键字(如
命名规范
虽然命名规则规定了标识符的合法性,但为了保持代码的可读性和一致性,通常还会遵循一些命名规范:
-
类名
- 使用大写开头的驼峰命名法(Pascal Case)。
- 示例:
MyClass
,EmployeeDetails
-
变量名和方法名
- 使用小写开头的驼峰命名法(Camel Case)。
- 示例:
myVariable
,calculateSalary
-
常量
- 使用全大写字母和下划线分隔词。
- 示例:
MAX_VALUE
,PI
-
包名
- 规范是使用全小写字母,并且层级由点号分隔。
- 通常以公司域名的反转形式开始。
- 示例:
com.example.myapp
-
接口名
- 通常也使用大写开头的驼峰命名法,并且可以使用形容词形式。
- 示例:
Runnable
,Iterable
public class Employee {
private String name;
private int age;
private static final int MAX_AGE = 65;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age <= MAX_AGE) {
this.age = age;
}
}
public static void main(String[] args) {
Employee emp = new Employee("John", 30);
System.out.println("Name: " + emp.getName());
System.out.println("Age: " + emp.getAge());
}
}
在这个示例中:
Employee
是一个类名,使用大写开头的驼峰命名法。name
,age
是变量名,使用小写开头的驼峰命名法。MAX_AGE
是常量,使用全大写字母和下划线。- 方法名如
getName
,setName
,main
使用小写开头的驼峰命名法。
扫描器
示例:
//导入Scanner类,属于util包里面
import java.util.Scanner;
public class myScanner {
public static void main(String[] args) {
//新建一个Scanner对象myScannner
Scanner myScanner = new Scanner(System.in);
System.out.println("################输入人员信息###############");
System.out.println("输入姓名:");
String name = myScanner.next();
System.out.println("姓名:" + name);
System.out.println("输入年龄:");
int age = myScanner.nextInt();
System.out.println("年龄:" + age);
System.out.println("输入薪资:");
double sty = myScanner.nextDouble();
System.out.println("薪资:" + sty);
//System.out.println("姓名:" + name +"\t年龄:"+ age +"\t薪资:"+ sty );
System.out.printf("姓名:%s\t年龄:%d\t薪资:%.2f",name,age,sty);
}
}
运行结果:
################输入人员信息###############
输入姓名:
liha
姓名:liha
输入年龄:
21
年龄:21
输入薪资:
10000.1
薪资:10000.1
姓名:liha 年龄:21 薪资:10000.1
进制介绍
以下是二进制
、八进制
、十进制
和十六进制
的对应表格:
十进制 (Decimal) | 二进制 (Binary) | 八进制 (Octal) | 十六进制 (Hexadecimal) |
---|---|---|---|
0 | 0000 | 0 | 0 |
1 | 0001 | 1 | 1 |
2 | 0010 | 2 | 2 |
3 | 0011 | 3 | 3 |
4 | 0100 | 4 | 4 |
5 | 0101 | 5 | 5 |
6 | 0110 | 6 | 6 |
7 | 0111 | 7 | 7 |
8 | 1000 | 10 | 8 |
9 | 1001 | 11 | 9 |
10 | 1010 | 12 | A |
11 | 1011 | 13 | B |
12 | 1100 | 14 | C |
13 | 1101 | 15 | D |
14 | 1110 | 16 | E |
15 | 1111 | 17 | F |
16 | 10000 | 20 | 10 |
下面详细介绍一下进制之间的转换及相关技巧
:
一、十进制转换为其他进制
1. 十进制转换为二进制
-
方法:将十进制数不断
除以
2,取余数
,直到商为0
,然后将余数逆序排列
。 -
例子:把10转换为二进制
- 10 ÷ 2 = 5,余0
- 5 ÷ 2 = 2,余1
- 2 ÷ 2 = 1,余0
- 1 ÷ 2 = 0,余1
最终结果: 1 0 10 = 101 0 2 10_{10} = 1010_{2} 1010=10102
2. 十进制转换为八进制
-
方法:将十进制数不断
除以8
,取余数
,直到商为0
,然后将余数逆序排列
。 -
例子:把83转换为八进制
- 83 ÷ 8 = 10,余3
- 10 ÷ 8 = 1,余2
- 1 ÷ 8 = 0,余1
最终结果: 8 3 10 = 12 3 8 83_{10} = 123_{8} 8310=1238
3. 十进制转换为十六进制
- 方法:将十进制数
不断除以16
,取余数
,直到商为0
,然后将余数逆序排列
(注意用A、B、C、D、E、F表示10、11、12、13、14、15)。 - 例子:把254转换为十六进制
- 254 ÷ 16 = 15,余14(E)
- 15 ÷ 16 = 0,余15(F)
最终结果: 25 4 10 = F E 16 254_{10} = FE_{16} 25410=FE16
- 例子: 把983转换为十六进制
- 16 61 余 … 7
- 16 3 余… 13 (D)
最终结果: 98 3 10 = 3 D 7 16 983_{10} = 3D7_{16} 98310=3D716
二、其他进制转换为十进制
1. 二进制转换为十进制
- 方法:将二进制数每位上的数字
乘以2
的对应次幂
,然后求和。 - 例子:把1010转换为十进制
101 0 2 = 1 × 2 3 + 0 × 2 2 + 1 × 2 1 + 0 × 2 0 = 8 + 0 + 2 + 0 = 1 0 10 1010_{2} = 1 \times 2^3 + 0 \times 2^2 + 1 \times 2^1 + 0 \times 2^0 = 8 + 0 + 2 + 0 = 10_{10} 10102=1×23+0×22+1×21+0×20=8+0+2+0=1010
2. 八进制转换为十进制
- 方法:将八进制数每位上的数字
乘以
8的对应次幂
,然后求和。 - 例子:把123转换为十进制
12 3 8 = 1 × 8 2 + 2 × 8 1 + 3 × 8 0 = 64 + 16 + 3 = 8 3 10 123_{8} = 1 \times 8^2 + 2 \times 8^1 + 3 \times 8^0 = 64 + 16 + 3 = 83_{10} 1238=1×82+2×81+3×80=64+16+3=8310
3. 十六进制转换为十进制
- 方法:将十六进制每位上的数字
乘以16
的对应次幂
,然后求和(字母A-F对应十进制的10-15)。 - 例子:把FE转换为十进制
F E 16 = 15 × 1 6 1 + 14 × 1 6 0 = 240 + 14 = 25 4 10 FE_{16} = 15 \times 16^1 + 14 \times 16^0 = 240 + 14 = 254_{10} FE16=15×161+14×160=240+14=25410
三、其他进制之间的转换
1. 二进制转换为八进制
-
方法:将二进制数
每三位一组
(从右向左)分组,不足三位
的左边补零
,每组转换为对应的八进制数。 -
例子:把101010转换为八进制
- 分组:101 010
- 组转换: 10 1 2 = 5 8 101_2 = 5_8 1012=58, 01 0 2 = 2 8 010_2 = 2_8 0102=28
最终结果: 10101 0 2 = 5 2 8 101010_{2} = 52_{8} 1010102=528
2. 二进制转换为十六进制
-
方法:将二进制数每
四位一组
(从右向左)分组,不足四位
的左边补零
,每组转换为对应的十六进制数。 -
例子:把110101转换为十六进制
- 分组:0011 0101
- 组转换: 001 1 2 = 3 16 0011_2 = 3_{16} 00112=316, 010 1 2 = 5 16 0101_2 = 5_{16} 01012=516
最终结果: 11010 1 2 = 3 5 16 110101_{2} = 35_{16} 1101012=3516
3. 八进制转换为二进制
-
方法:将八进制数每个数字转换为
三位
二进制数。 -
例子:把52转换为二进制
- 5 8 = 10 1 2 5_8 = 101_2 58=1012
- 2 8 = 01 0 2 2_8 = 010_2 28=0102
最终结果: 5 2 8 = 10101 0 2 52_{8} = 101010_{2} 528=1010102
4. 十六进制转换为二进制
-
方法:将十六进制数每个数字转换为
四位
二进制数。 -
例子:把3E转换为二进制
- 3 16 = 001 1 2 3_{16} = 0011_2 316=00112
- E 16 = 111 0 2 E_{16} = 1110_2 E16=11102
最终结果: 3 E 16 = 0011111 0 2 3E_{16} = 00111110_{2} 3E16=001111102
原码、反码、补码
原码
原理:
- 源码是一种最基础的二进制编码方式,直接根据数值的正负进行表示。对于正数,源码就是其二进制表示;对于负数,源码在正数二进制表示的基础上将最高位设为1,来表示负号。
规则:
- 最高位为符号位:0表示正数,1表示负数
- 其余位为数值部分的二进制表示
反码
原理:
- 反码是在源码的基础上,将数值部分(除符号位以外)逐位取反,1变成0,0变成1。
规则:
- 对于正数,反码与源码相同。
- 对于负数,符号位保留,其余位逐位取反。
补码
原理:
- 补码是在反码的基础上加1,是计算机处理中负数的标准表示方式,因为补码运算可以简化加减运算。
规则:
- 对于正数,补码和源码相同。
- 对于负数,在反码的基础上加1。
位运算
下面采用一个例子更好的理解源码、反码和补码的原理。
实例说明 ~2
和 ~-2
的计算过程
假设使用 int
数据类型(在大多数编程语言中,int
通常占用32位)进行以下示例。
1. 计算 2
的源码、反码、补码
十进制数 2
在二进制下的表示为:00000000 00000000 00000000 00000010
-
源码(原码):
2
的源码为:00000000 00000000 00000000 00000010
-
反码:
- 对于正数,反码与源码相同:
00000000 00000000 00000000 00000010
- 对于正数,反码与源码相同:
-
补码:
- 对于正数,补码与源码相同:
00000000 00000000 00000000 00000010
- 对于正数,补码与源码相同:
2. 按位取反 ~2
的结果
按位取反 ~2
:
- 取反每一位:
11111111 11111111 11111111 11111101
3. 结果转换回十进制
由于最高位是1,表示这是一个负数:
- 先找到其补码对应的负数:
- 反码:
00000000 00000000 00000000 00000010
- 加 1:
00000000 00000000 00000000 00000011
- 对应十进制数为
3
- 反码:
- 因为符号位为1,表示负数,所以结果为
-3
结论:~2
按位取反后的十进制结果为 -3
4. 计算 -2
的源码、反码、补码
十进制数 -2
的计算过程:
-
源码:
-2
的源码为:10000000 00000000 00000000 00000010
-
反码:
- 除符号位外逐位取反:
11111111 11111111 11111111 11111101
- 除符号位外逐位取反:
-
补码:
- 在反码基础上加1:
11111111 11111111 11111111 111111#### 5. 按位取反
~-2` 的结果
- 在反码基础上加1:
-
取反每一位:
00000000 00000000 00000000 00000001
5. 结果转换回十进制
由于这是一个正数(最高位为0),直接转换:
- 二进制
00000000 00000000 00000000 00000001
对应十进制为1
结论:~-2
按位取反后的十进制结果为 1
综合总结
通过源码、反码和补码的原理和具体示例计算,得到以下结果:
2
的源码、反码和补码:00000000 00000000 00000000 00000010
~2
在转换为十进制后的结果为-3
-2
的源码:10000000 00000000 00000000 00000010
-2
的反码:11111111 11111111 11111111 11111101
-2
的补码:11111111 11111111 11111111 11111110
~-2
在转换为十进制后的结果为1
运算左移、运算右移、无符号左移、无符号右移
运算左移、运算右移和无符号右移的比较
我们以一个8位二进制数为例:10110011
,并对其进行左移、运算右移和无符号右移的操作。假设这个二进制数表示的是有符号的整数。
操作类型 | 操作符 | 初始值 | 移位方向与次数 | 结果 | 具体解释 |
---|---|---|---|---|---|
运算左移 | << | 10110011 | 左移1位 | 01100110 | 左移操作会使该数字的二进制位整体向左移动,每次左移一位,最低位补0。左移相当于乘以2的相应次幂。 |
运算左移 | << | 10110011 | 左移2位 | 11001100 | 左移操作会使该数字的二进制位整体向左移动,每次左移一位,最低位补0。左移相当于乘以2的相应次幂。 |
运算右移 | >> | 10110011 | 右移1位 | 11011001 | 右移操作会使该数字的二进制位整体向右移动,每次右移一位,最高位保持原来的符号位。右移相当于整除2的相应次幂。 |
运算右移 | >> | 10110011 | 右移2位 | 11101100 | 右移操作会使该数字的二进制位整体向右移动,每次右移一位,最高位保持原来的符号位。右移相当于整除2的相应次幂。 |
无符号右移 | >>> | 10110011 | 右移1位 | 01011001 | 无符号右移不考虑符号位,直接右移并在高位补0。这使得无论是正数还是负数,其高位均补0。 |
无符号右移 | >>> | 10110011 | 右移2位 | 00101100 | 无符号右移不考虑符号位,直接右移并在高位补0。这使得无论是正数还是负数,其高位均补0。 |
-
运算左移(<<):
- 左移1位
初始值:10110011
左移1位:01100110
- 左移2位
初始值:10110011
左移2位:11001100
- 左移1位
-
运算右移(>>):
- 右移1位
初始值:10110011
右移1位:11011001
- 右移2位
初始值:10110011
右移2位:11101100
- 右移1位
-
无符号右移(>>>):
- 右移1位
初始值:10110011
右移1位:01011001
- 右移2位
初始值:10110011
右移2位:00101100
- 右移1位
负数运算左移
详细地分解向右移2位的过程,包括每一步的操作和每一位的变化过程。
初始值:
我们从一个32位的补码表示开始:
初始值: -1(32位二进制表示)
11111111 11111111 11111111 11111111
第一步:识别符号位:
有符号右移操作会保留符号位。在补码表示中,最高位(最左边一位)是符号位。如果符号位是1,表示负数;是0,表示正数。
在这个例子中,最高位是1,表示这是一个负数。
第二步:位移过程:
向右移位的过程中,我们将最低的位移出并向高位补充符号位。
- 第一次右移::
原始值: 11111111 11111111 11111111 11111111
右移1位: 11111111 11111111 11111111 11111111
解释:最高位补1(符号位),最低位1被移出,二进制数字变成: 11111111 11111111 11111111 11111111
- 第二次右移::
右移1位: 11111111 11111111 11111111 11111111 >> 1
原始值: 11111111 11111111 11111111 11111111
右移2位: 11111111 11111111 11111111 11111111
解释:再次右移,最高位继续补1(符号位),最低位1再次被移出。二进制数字保持不变:11111111 11111111 11111111 11111111
检查和校验结果:
最终的结果依旧是:
11111111 11111111 11111111 11111111
补码确认:
这依旧是补码形式表示的 -1。如果将其转换回十进制数,可以看到结果与初始值相同。
验证Java代码:
运行以下Java代码也可验证:
public class RightShiftDemo {
public static void main(String[] args) {
int b = -1 >> 2;
System.out.println(b); // 输出应为 -1
}
}
运行结果将是:
-1
更详细的分解
在每一步具体的移位过程中:
-
第一步移位:
- 原始值:
11111111 11111111 11111111 11111111
- 右移1位:
11111111 11111111 11111111 11111111
(最高位补符号位1,最低位1移出)
- 原始值:
-
第二步移位:
- 中间值:
1111111 11111111 11111111 11111111
(保持不变) - 右移2位:
11111111 11111111 11111111 11111111
(最高位补符号位1,最低位1移出)
- 中间值:
最终的结果为:
11111111 11111111 11111111 11111111 (对应十进制 -1)
如此,完整的向右移2位的过程清晰展示了符号位的保持以及补码的处理方式。结果如下所述,int b = -1 >> 2
的最终结果是 -1。
分支控制if-else
作业:
题目一:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
double a , b ;
Scanner input = new Scanner(System.in);
System.out.println("输入a的值:");
a = input.nextDouble();
System.out.println("输入b的值:");
b = input.nextDouble();
if(a > 10.0 && b < 20.0) {
System.out.println(a+b);
}
}
}
运行结果:
输入a的值:
11.2
输入b的值:
19.432
30.631999999999998
题目二:
import java.util.Scanner;
public class myScanner {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("输入数字a:");
int a = input.nextInt();
System.out.println("输入数字b:");
int b = input.nextInt();
int c = a + b ;
if ( c % 3 == 0 && c %5 == 0){
System.out.printf("数字c的值%d能够被整除",c);
}else
System.out.printf("数字c的值%d不能够被整除",c);
}
}
运行结果:
输入数字a:
13
输入数字b:
17
数字c的值30能够被整除
题目三:
import java.util.Scanner;
public class myScanner01 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("输入需要判断的年份:");
int a = input.nextInt();
// for (int i = 1000 ;i <= 2024; i++){
if ( a % 4 == 0 && a % 100 != 0 || a % 400 == 0){
System.out.printf("该%d年份为闰年\n",a);
}else
System.out.printf("该%d年份不为闰年\n",a);
}
// }
}
运行结果:
输入需要判断的年份:
2024
该2024年份为闰年
嵌套分支
题目一:
代码:
import java.util.Scanner;
public class myScanner02 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("输入月份:");
int month = input.nextInt();
int sum;
if (month >= 4 && month <= 10){
System.out.println("该季节为旅游旺季!");
System.out.println("成人(18-60):60元");
System.out.println("儿童(<18):半价");
System.out.println("老人(>60):1/3");
System.out.println("请输入成人数量:");
int adults = input.nextInt();
System.out.println("请输入儿童数量:");
int children = input.nextInt();
System.out.println("请输入老人数量:");
int seniors = input.nextInt();
sum = 60 * adults + 30 * children + 20 * seniors;
System.out.printf("总票价为:%d",sum);
}else{
System.out.println("该季节为旅游淡季!");
System.out.println("成人(18-60):60元");
System.out.println("其他:20元");
System.out.println("请输入成人数量:");
int adults = input.nextInt();
System.out.println("请输入儿童数量:");
int children = input.nextInt();
System.out.println("请输入老人数量:");
int seniors = input.nextInt();
sum = 60 * adults + 30 * children + 20 * seniors;
System.out.printf("总票价为:%d",sum);
}
}
}
运行结果:
输入月份:6
该季节为旅游旺季!
成人(18-60):60元
儿童(<18):半价
老人(>60):1/3
请输入成人数量:
3
请输入儿童数量:
3
请输入老人数量:
4
总票价为:350
Switch分支
switch流程图:
快速入门:
Java中的switch
语句是一种多分支选择控制结构,用来替代多重的if-else
语句,使代码更加简洁和可读。它可以根据表达式的值,执行相应的代码块。
switch
语句的基本语法
switch (expression) {
case value1:
// 代码块1
break;
case value2:
// 代码块2
break;
// 可以有任意数量的case语句
default:
// 默认代码块
}
详细解释
-
表达式 (expression):
- 表达式的数据类型可以是
byte
、short
、int
、char
、String
(从Java 7开始支持)或枚举类型。 - 表达式的值将与每个
case
标签进行比较,匹配的代码块将被执行。
- 表达式的数据类型可以是
-
case标签:
case
后跟要比较的值,每个值后面是一个冒号。- 当表达式的值与某个
case
标签的值匹配时,执行相应的代码块。 - 每个
case
标签通常以break
语句结束,以防止继续执行后续的case
代码块。
-
break语句:
break
语句用于终止switch
语句,跳出switch
结构。如果省略break
,程序将继续执行下一个case
或default
代码块(这被称为“穿透”)。
-
default标签:
default
代码块是可选的,但建议包括在内。- 当表达式的值不匹配任何一个
case
标签时,执行default
代码块。
示例代码
下面是一个简单的示例,展示了如何使用switch
语句:
import java.util.Scanner;
public class SwitchExample {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入一个数字 (1-7):");
int day = input.nextInt();
switch (day) {
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
case 5:
System.out.println("星期五");
break;
case 6:
System.out.println("星期六");
break;
case 7:
System.out.println("星期日");
break;
default:
System.out.println("无效的输入");
break;
}
input.close();
}
}
注意事项
- 表达式类型: 表达式的数据类型必须是
byte
、short
、int
、char
、String
或枚举类型。其他类型,如long
、float
、double
和布尔类型,是不允许的。 - 穿透现象: 如果在
case
代码块末尾没有break
语句,则会继续执行下一个case
代码块,直到遇到break
或switch
语句结束。这在有意时可以用于多个case
共享代码,但一般情况下应避免。 - case标签的值必须唯一: 每个
case
标签的值在同一个switch
语句中必须是唯一的,不能重复。
通过使用switch
语句,可以使代码逻辑更加清晰、简洁,尤其是在处理多个条件分支时。
例子:如果不加break
import java.util.Scanner;
public class Switch01{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("请输入字母:");
String str1 = input.next();
char c = str1.charAt(0);
switch (c){
case 'a':
System.out.print("星期一");
case 'b':
System.out.print("星期二");
case 'c':
System.out.print("星期三");
case 'd':
System.out.print("星期四");
case 'f':
System.out.print("星期五");
case 'g':
System.out.print("星期六");
default:
System.out.print("星期日");
}
}
}
运行:
请输入字母:
c
星期三星期四星期五星期六星期日
加上break
:
import java.util.Scanner;
public class Switch01{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("请输入字母:");
String str1 = input.next();
char c = str1.charAt(0);
switch (c){
case 'a':
System.out.print("星期一");
break;
case 'b':
System.out.print("星期二");
break;
case 'c':
System.out.print("星期三");
break;
case 'd':
System.out.print("星期四");
break;
case 'f':
System.out.print("星期五");
break;
case 'g':
System.out.print("星期六");
break;
default:
System.out.print("星期日");
}
}
}
运行:
请输入字母:
c
星期三
Switch分支结构细节
题目1:
题目一代码:
import java.util.Scanner;
public class Switch02{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("请输入字母:");
char c = input.next().charAt(0);
String s ;
switch (c){
case 'a':
s = c + "";
s = s.toUpperCase();
System.out.println(s);
break;
case 'b':
s = c + "";
s = s.toUpperCase();
System.out.println(s);
break;
case 'c':
s = c + "";
s = s.toUpperCase();
System.out.println(s);
break;
case 'd':
s = c + "";
s = s.toUpperCase();
System.out.println(s);
break;
case 'e':
s = c + "";
s = s.toUpperCase();
System.out.println(s);
break;
default:
s = "other".toUpperCase();
System.out.println(s);
break;
}
}
}
详解:
在 Java 中,将字符串中的小写字母转换成大写并不需要使用特定的包,因为这个功能已经内置在 Java 的标准类库中,具体是 String
类的一部分。String
类提供了一个非常方便的方法 toUpperCase()
来将字符串中的所有小写字母转换为大写字母。
下面是如何使用 toUpperCase()
方法来转换字符串的一个基本示例:
示例代码
public class Main {
public static void main(String[] args) {
String original = "hello world";
String upperCased = original.toUpperCase();
System.out.println("原始字符串: " + original);
System.out.println("转换后的字符串: " + upperCased);
}
}
在这个示例中,我们先定义了一个包含小写字母的字符串 original
,然后调用 toUpperCase()
方法来得到全部大写的字符串 upperCased
,最后输出原始字符串和转换后的字符串。
细节说明
-
方法功能:
toUpperCase()
将字符串中所有小写字母转换成对应的大写字母。 -
国际化支持:
toUpperCase()
方法默认使用系统的默认区域设置来进行大小写转换。如果你需要根据特定的语言环境(Locale)来做转换(一些语言的大小写转换规则可能与英语有所不同),可以使用带有 Locale 参数的toUpperCase(Locale locale)
方法。例如,对于土耳其语,字符 ‘i’ 转换为大写时需要特别注意:
String turkish = "i"; String turkishUpper = turkish.toUpperCase(Locale.forLanguageTag("tr")); System.out.println(turkishUpper); // 输出 "İ"
-
性能考虑:字符串操作尤其是在循环或大量数据处理中要注意性能。尽管
toUpperCase()
是高效实现的,但不必要的使用应当避免,特别是在大数据量处理时。
通过以上解释和示例,你应该能够理解如何在 Java 中将字符串从小写转换为大写了。
题目2:
import java.util.Scanner;
public class Switch02{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("请输入学习成绩:");
int c = input.nextInt();
String s ;
if (c > 60 && c <= 100 ){
s = "true";
}else s = "false";
switch (s){
case "true" :
System.out.println("合格");
break;
default:
System.out.println("不合格");
}
}
}
这段 Java 代码使用了Scanner
类来从控制台接收用户输入的学习成绩,并使用if-else
语句和switch-case
结构对成绩进行简单的合格(“合格”)与不合格(“不合格”)判断。下面是这段代码的详细解释:
-
代码首先通过
import java.util.Scanner;
语句导入了Scanner
类,这是使用这个类的前提。 -
在
Switch02
类中的main
方法里,首先创建了Scanner
对象input
,用来从标准输入(这里是控制台)读取数据。 -
接着,程序输出提示信息
"请输入学习成绩:"
,告诉用户输入成绩。 -
用户输入的成绩被
nextInt()
方法读取,并存储在整数变量c
中。 -
使用
if-else
语句根据成绩c
的值来设置字符串变量s
的值。如果成绩在60到100之间(包括60和100),s
被赋值为"true"
;否则,s
被赋值为"false"
。 -
使用
switch
语句基于s
的值选择分支。如果s
等于"true"
,则输出"合格"
并结束switch
结构(因为有break
语句);如果s
为任何其他值(这里只可能是"false"
),则执行default
分支,输出"不合格"
。
这段代码虽然实现了功能,但其实使用switch
语句来处理这种情况显得有些多余,直接使用if-else
语句会更简洁。例如,可以不需要将成绩判断的结果转换成字符串(“true"或"false”),直接在if-else
结构中输出结果:
import java.util.Scanner;
public class Switch02{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("请输入学习成绩:");
int c = input.nextInt();
if (c >= 60 && c <= 100){
System.out.println("合格");
} else {
System.out.println("不合格");
}
}
}
这样的代码更为直接和易于理解。
题目3:
在 Java 中,可以使用一个 switch
语句来实现根据月份打印其所属季节的功能。switch
语句的穿透特性使得相同的操作可以应用于多个 case
,直到遇到 break
语句为止。
下面是一个完整的 Java 程序示例,展示如何使用 switch
语句和穿透来实现这一功能:
import java.util.Scanner;
public class SeasonByMonth {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入月份 (1-12):");
int month = input.nextInt();
if (month < 1 || month > 12) {
System.out.println("错误的月份输入。请确保输入的是1到12之间的数。");
} else {
switch (month) {
case 3:
case 4:
case 5:
System.out.println(month + "月是春季。");
break;
case 6:
case 7:
case 8:
System.out.println(month + "月是夏季。");
break;
case 9:
case 10:
case 11:
System.out.println(month + "月是秋季。");
break;
case 12:
case 1:
case 2:
System.out.println(month + "月是冬季。");
break;
}
}
}
}
代码详解:
- 输入月份:用户被提示输入一个月份(1 至 12)。
- 有效性检查:程序首先检查用户输入的月份是否在有效范围内(1到12)。如果输入无效,则输出错误消息并终止程序。
- 使用
switch
语句:根据用户输入的月份,switch
语句将执行匹配的case
语句块。由于使用了穿透特性(即在每个季节的最后一个月份之前不放break
),在找到匹配的case
后,所有相关的月份都会执行相同的代码,直到遇到break
,此时switch
结束。 - 打印结果:程序将输出相应月份所属的季节。
这段代码高效地展示了如何利用 switch
语句的穿透特性来为多个条件执行相同的动作。
如何正确选用Switch
和if-esle
在编写 Java 程序时,switch
和 if-else
语句都是控制流结构,可以根据条件执行不同的代码块。选择使用哪种结构取决于具体的需求和情况。以下是一些指导原则,帮助你决定何时使用 switch
或 if-else
:
使用 switch
的情况
-
多个离散值:
- 当需要基于一个变量的多个离散值进行分支时,
switch
语句通常是更好的选择。例如,处理星期几、月份或状态码等。 switch
语句可以提高代码的可读性和清晰度。
- 当需要基于一个变量的多个离散值进行分支时,
-
常量表达式:
switch
语句适用于基于常量表达式(如整数、枚举、字符和字符串)进行的判断。
-
性能:
- 在某些情况下,特别是当有许多条件时,
switch
语句可能比多个if-else
语句具有更好的性能,因为编译器可以对switch
语句进行优化。
- 在某些情况下,特别是当有许多条件时,
使用 if-else
的情况
-
复杂条件:
- 当条件不仅仅是简单的相等比较时,例如范围判断(大于、小于等),或者条件包含逻辑运算符(如 AND、OR)时,使用
if-else
语句会更适合。
- 当条件不仅仅是简单的相等比较时,例如范围判断(大于、小于等),或者条件包含逻辑运算符(如 AND、OR)时,使用
-
简单条件:
- 当只有少量的分支,特别是只有两个或三个分支时,
if-else
语句可能会更简洁。
- 当只有少量的分支,特别是只有两个或三个分支时,
-
非常量表达式:
- 当条件基于动态计算结果、非常量值或复杂逻辑时,
if-else
语句是必需的,因为switch
语句只支持常量表达式。
- 当条件基于动态计算结果、非常量值或复杂逻辑时,
总结
switch
:适合多个离散值、常量表达式,代码更清晰。if-else
:适合复杂条件、非常量表达式和逻辑运算。
在 Java 中,if-else
语句的条件表达式必须是一个布尔类型的值 (boolean
) 或能够计算出一个布尔类型的结果。这意味着条件表达式要么直接是一个布尔变量,要么是一个能够产生布尔结果的表达式。
示例 1:布尔变量
boolean isTrue = true;
if (isTrue) {
System.out.println("条件为真");
} else {
System.out.println("条件为假");
}
示例 2:布尔表达式
int a = 10;
int b = 20;
if (a < b) {
System.out.println("a 小于 b");
} else {
System.out.println("a 不小于 b");
}
示例 3:复杂布尔表达式
int x = 5;
int y = 10;
if (x > 0 && y > 0) {
System.out.println("x 和 y 都是正数");
} else {
System.out.println("x 或 y 不是正数");
}
错误示例:非布尔值
条件表达式不能是非布尔类型的值,例如整数或字符串。这将导致编译错误。
int num = 10;
// 错误:条件表达式不是布尔类型
if (num) {
System.out.println("这是错误的用法");
}
if-else
语句的条件表达式只能是布尔值或能产生布尔结果的表达式。这保证了条件表达式在执行时能够明确地评估为 true
或 false
,从而决定执行哪个代码块。
for循环
for循环控制
注意事项
Java中的for
循环是一种常用的控制流语句,用于在满足条件的情况下多次执行一段代码。它的基本语法如下:
for (初始化; 条件; 更新) {
// 循环体
}
语法详解
-
初始化(Initialization): 在循环开始之前执行的语句,通常用于声明并初始化循环控制变量。只执行一次。
int i = 0;
-
条件(Condition): 每次循环开始前都会检查这个条件,如果为
true
,则执行循环体,否则退出循环。i < 10;
-
更新(Update): 每次执行完循环体之后,更新循环控制变量的语句。
i++;
使用示例
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
上面的代码会输出从0到9的数字。它的工作原理如下:
- 初始化:
int i = 0;
- 条件检查:
i < 10;
(初始i
为0,条件为true
) - 执行循环体:
System.out.println(i);
- 更新:
i++
(i
变为1) - 重复步骤2到4,直到条件为
false
注意事项
-
循环条件: 确保循环条件能够在某一时刻变为
false
,否则会导致死循环。for (int i = 0; i < 10; ) { System.out.println(i); // 没有更新i的语句,导致死循环 }
-
控制变量的作用域: 循环控制变量的作用域仅限于
for
循环内部。for (int i = 0; i < 10; i++) { // i 在此范围内有效 } // i 在此处不可访问
-
循环体内改变控制变量: 避免在循环体内改变控制变量,这会使代码难以理解和维护。
for (int i = 0; i < 10; i++) { i += 2; // 使得循环不按预期运行 }
-
增强型
for
循环(foreach): 用于遍历数组或集合。int[] arr = {1, 2, 3, 4, 5}; for (int num : arr) { System.out.println(num); }
增强型
for
循环不需要手动管理循环变量,简化了代码,减少了出错的可能性。
例子和实践
嵌套循环:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.println("i = " + i + ", j = " + j);
}
}
输出:
i = 0, j = 0
i = 0, j = 1
i = 0, j = 2
i = 1, j = 0
i = 1, j = 1
i = 1, j = 2
i = 2, j = 0
i = 2, j = 1
i = 2, j = 2
提前退出循环:
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // 提前退出循环
}
System.out.println(i);
}
输出:
0
1
2
3
4
跳过当前迭代:
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
continue; // 跳过当前迭代
}
System.out.println(i);
}
输出:
1
3
5
7
9
这些示例展示了for
循环在Java中的多种用法及其细节。通过合理使用for
循环,可以高效地处理重复任务。
代码示例:
public class For01{
public static void main(String[] args){
for (int i = 0 ;i <= 10; i++){
System.out.println("hello.韩顺平"+i);
}
}
}
也可以这样写:
public class For01{
public static void main(String[] args){
int i = 0;
for (;i <= 10;){
System.out.println("hello.韩顺平"+i);
i++;
}
System.out.println(i);
}
}
运行结果:
hello.韩顺平0
hello.韩顺平1
hello.韩顺平2
hello.韩顺平3
hello.韩顺平4
hello.韩顺平5
hello.韩顺平6
hello.韩顺平7
hello.韩顺平8
hello.韩顺平9
hello.韩顺平10
11
无限死循环
示例:
public class For01{
public static void main(String[] args){
int i = 0;
for (;;){ //无限死循环;
System.out.println("hello.韩顺平"+i);
i++;
}
}
}
作业题
题目一:
public class For01{
public static void main(String[] args){
int count = 0 , a = 0;
for (int i = 1; i<=100 ;i++){
if (i % 9 == 0){
count+=i;
a++;
System.out.println("个数:"+a+" 值:"+i);
}
}
System.out.println("个数:"+a+" 总和:"+count);
}
}
运行结果:
个数:1 值:9
个数:2 值:18
个数:3 值:27
个数:4 值:36
个数:5 值:45
个数:6 值:54
个数:7 值:63
个数:8 值:72
个数:9 值:81
个数:10 值:90
个数:11 值:99
个数:11 总和:594
题目拓展:
起始值
和结束值
以及倍数
都是变量表示
import java.util.Scanner;
public class For01{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("输入起始值:");
int sum = input.nextInt();
System.out.print("输入结束值:");
int sum2 = input.nextInt();
System.out.print("输入倍数:");
int sum3 = input.nextInt();
int count = 0 , a = 0;
for (int i = sum; i<=sum2 ;i++){
if (i % sum3 == 0){
count+=i;
a++;
System.out.println("个数:"+a+" 值:"+i);
}
}
System.out.println("个数:"+a+" 总和:"+count);
}
}
运行结果:
输入起始值:34
输入结束值:100
输入倍数:5
个数:1 值:35
个数:2 值:40
个数:3 值:45
个数:4 值:50
个数:5 值:55
个数:6 值:60
个数:7 值:65
个数:8 值:70
个数:9 值:75
个数:10 值:80
个数:11 值:85
个数:12 值:90
个数:13 值:95
个数:14 值:100
个数:14 总和:945
题目二:
public class For01{
public static void main(String[] args){
int count = 0 , a = 5;
for (;count <=5;count++,a-=1){
int i = count + a ;
System.out.println(count+" + "+a+" = "+ i);
}
}
}
这段代码定义了一个For01
类,包含一个main
方法。在这个方法中,使用了一个for
循环,循环条件是count <= 5
,每次循环count
递增1,而变量a
递减1。每次循环中,计算count
和a
的和,并输出。
我们来逐步解析这段代码:
-
变量初始化:
count
初始化为0。a
初始化为5。
-
for
循环:- 循环条件:
count <= 5
。 - 每次循环之后,
count
增加1,a
减少1。
- 循环条件:
-
循环体:
- 计算
i = count + a
。 - 打印
count + " + " + a + " = " + i
。
- 计算
代码运行分析
让我们逐步分析每次循环中的变量变化:
- 初始状态:
count = 0
,a = 5
- 第一次循环:
count = 0
,a = 5
,i = 0 + 5 = 5
- 第二次循环:
count = 1
,a = 4
,i = 1 + 4 = 5
- 第三次循环:
count = 2
,a = 3
,i = 2 + 3 = 5
- 第四次循环:
count = 3
,a = 2
,i = 3 + 2 = 5
- 第五次循环:
count = 4
,a = 1
,i = 4 + 1 = 5
- 第六次循环:
count = 5
,a = 0
,i = 5 + 0 = 5
代码输出
当你运行这段代码时,输出将如下:
0 + 5 = 5
1 + 4 = 5
2 + 3 = 5
3 + 2 = 5
4 + 1 = 5
5 + 0 = 5
这个程序演示了for
循环的使用,其中初始条件部分为空,循环条件为count <= 5
,每次循环后count
增加1,a
减少1。循环体中计算了count
和a
的和,并输出结果。
While循环
while循环流程图
Java中的while
循环是基础的控制流结构之一,用于在满足特定条件的情况下重复执行一段代码。这种类型的循环对于执行次数未知的任务特别有用。
基本语法
while
循环的基本语法是:
while (条件表达式) {
// 循环体代码
}
在这里,“条件表达式”是一个必须返回布尔值(true 或 false)的表达式。只要该表达式评估为true,循环体内的代码就会重复执行。
使用示例
int i = 0;
while (i < 5) {
System.out.println("i 的值是: " + i);
i++; // 很重要,确保循环能够结束
}
在这个例子中,我们初始化变量i
为0,然后while
循环会持续执行,直到i
的值不再小于5。每次循环结束时,都会通过i++
来增加i
的值。
使用细节和注意事项
-
确保循环可以结束:需要在循环体内部改变条件表达式的值,否则可能导致无限循环。在上例中,我们通过
i++
来确保最终i
的值会达到5,使条件i < 5
最终变为false
,从而结束循环。 -
初始化条件变量:通常在进入
while
循环之前需要初始化一个或多个条件变量,这些变量会在条件表达式中使用。如果没有正确初始化这些变量,可能导致程序错误。 -
循环体执行次数:如果
while
循环的条件一开始就是false
,那么循环体内的代码一次也不会执行。这与do-while
循环不同,后者至少会执行一次循环体。 -
使用适当的条件表达式:条件表达式不应该过于复杂,以避免出现逻辑错误。简单明了的逻辑更容易维护和理解。
-
注意变量作用域:在
while
循环中声明的变量仅在循环内部有效。如果需要在循上后续的代码中访问循环中的变量,应该在循环外部声明这些变量。 -
避免死循环:确保有一个显式的退出循环的条件。如果循环的逻辑错误,可能会导致程序陷入无限循环,并且可能使程序卡死或消耗过多资源。
高级用法
while
循环可以嵌套使用,处理更复杂的情况,如多维数组的遍历或在满足多个条件的情况下重复执行任务。同时,while
循环可以与break
和continue
语句配合使用:
- break:立即退出最近的循环。
- continue:跳过当前的迭代,继综执行循环的下一次迭代。
int i = 0;
while (i < 10) {
if (i == 3) {
i++;
continue; // 跳过 i == 3 的情况
}
if (i == 8) {
break; // 当 i 到达 8 时结束循环
}
System.out.println("i 的值是: " + i);
i++;
}
代码举例说明:
public class While01{
public static void main(String[] args){
int i = 0; //循环变量初始化
while(i <= 10){
System.out.println("韩顺平"+i); //循环体(语句)
++i; //循环变量迭代
}
System.out.println("i="+i);
}
}
作业题
题目一:
import java.util.Scanner;
public class While01{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("输入起始值");
int start = input.nextInt();
System.out.println("输入结束值");
int end = input.nextInt();
int i = start , count = 0;
while(i >= start && i <= end){
if (i % 3 == 0){
count++;
System.out.println("i="+i);
}
i++;
}
System.out.println("count="+count);
运行结果:
输入起始值
30
输入结束值
50
i=30
i=33
i=36
i=39
i=42
i=45
i=48
count=7
题目二:
import java.util.Scanner;
public class While01{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("输入起始值");
int start = input.nextInt();
System.out.println("输入结束值");
int end = input.nextInt();
int i = start , count = 0;
while(i >= start && i <= end){
if (i % 2 == 0){
count++;
System.out.println("i="+i);
}
i++;
}
System.out.println("count="+count);
}
}
运行结果:
输入起始值
40
输入结束值
200
i=40
i=42
i=44
i=46
i=48
...
i=196
i=198
i=200
count=81
题目拓展:
起始值
和结束值
以及倍数
为变量
import java.util.Scanner;
public class While01{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("输入起始值:");
int start = input.nextInt();
System.out.print("输入结束值:");
int end = input.nextInt();
System.out.print("输入倍数:");
int multiple = input.nextInt();
int i = start , count = 0;
while(i >= start && i <= end){
if (i % multiple == 0){
count++;
System.out.println("i="+i);
}
i++;
}
System.out.println("count="+count);
}
}
运行结果:
入起始值:10
输入结束值:100
输入倍数:10
i=10
i=20
i=30
i=40
i=50
i=60
i=70
i=80
i=90
i=100
count=10
do…while循环
Java 的 do...while
语句是一种循环结构,确保循环体内的代码至少执行一次。即使循环条件一开始为假,循环体也会执行一次。其语法格式如下:
do {
// 循环体
// 变量迭代
} while (循环条件);
语法详释
- do:关键字,表示循环的开始。
- 循环体:需要重复执行的代码块。
- while (条件):循环的条件,循环体执行完毕后检查该条件。如果条件为真(
true
),则继续执行循环体,否则结束循环。
流程图
- 执行一次循环体中的代码。
- 判断条件是否成立。
- 如果条件为真(
true
),则返回步骤1,继续执行循环体。 - 如果条件为假(
false
),则结束循环。
- 如果条件为真(
示例代码1
public class DoWhileExample {
public static void main(String[] args) {
int count = 1;
do {
System.out.println("Count is: " + count);
count++;
} while (count <= 5);
}
}
示例解释:
- 初始化变量
count
为1。 - 进入
do
块,输出Count is: 1
,然后将count
加1。 - 检查条件
count <= 5
是否成立。如果成立,继续执行循环体。 - 如此循环,直到
count
大于5,循环结束。
示例代码2
import java.util.Scanner;
public class DoWhile01{
public static void main(String[] args){
System.out.println("请输入初始值:");
Scanner output = new Scanner(System.in);
int i = output.nextInt(); //变量初始化
do{
System.out.printf("hello,韩顺平%d!!\n",i); //循环体
i++; //循环变量迭代
}while(i<=10); //循环条件
System.out.println("结束do...while循环,继续执行..."+i);
}
}
执行结果:
请输入初始值:
2
hello,韩顺平2!!
hello,韩顺平3!!
hello,韩顺平4!!
hello,韩顺平5!!
hello,韩顺平6!!
hello,韩顺平7!!
hello,韩顺平8!!
hello,韩顺平9!!
hello,韩顺平10!!
结束do...while循环,继续执行...11
使用场景
do...while
语句适用于需要至少执行一次循环体的情况,例如用户输入验证、菜单选择等场景。
注意事项
- 如果循环条件一开始就为假,
do...while
仍然会执行一次循环体,这点与while
语句不同。 - 需要注意循环条件的变化,以避免造成无限循环。
作业题
题目一:
import java.util.Scanner;
public class DoWhile02{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("输入起始值:");
int i = input.nextInt();
do{
System.out.println(i);
i++;
}while(i>=0 && i<=100);
}
}
题目二:
import java.util.Scanner;
public class DoWhile02{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("输入起始值:");
int i = input.nextInt(),sum=0;
do{
sum+=i;
i++;
}while(i>=0 && i<=100);
System.out.print("i="+i+"\tsum="+sum);
}
}
运行结果:
输入起始值:0
i=101 sum=5050
题目三:
import java.util.Scanner;
public class DoWhile02{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.print("输入起始值:");
int i = input.nextInt(),sum=0;
do{
if (i%5== 0 && i%3 > 0){
System.out.println("i="+i);
sum++;
}
i++;
}while(i<=200);
System.out.print("i="+i+"\tsum="+sum);
}
}
运行结果:
输入起始值:0
i=5
i=10
i=20
i=25
i=35
i=40
i=50
i=55
i=65
i=70
i=80
i=85
i=95
i=100
i=110
i=115
i=125
i=130
i=140
i=145
i=155
i=160
i=170
i=175
i=185
i=190
i=200
i=201 sum=27
题目四:
import java.util.Scanner;
public class DoWhile02{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
String s = "";
do{
System.out.println("老韩生气的使出闪电五连鞭");
System.out.print("还不钱吗?回答[y/n]:");
s = input.next();
}while(!s.equals("y"));
System.out.println("老韩开心的嘴角微微上扬!");
}
}
如果希望在不等于某个特定值(比如 “y”)时进入循环,可以在 while
条件中使用 !s.equals("y")
。这样,只要用户输入的不是 “y”,循环就会继续执行。
代码解释:
- 创建一个
Scanner
对象用于从控制台读取输入。 - 使用
do...while
循环,确保循环体至少执行一次。 - 在每次循环中,提示用户输入并读取输入。
- 使用
!s.equals("y")
方法比较输入字符串,如果输入不是"y"
,则继续循环,否则退出循环。 - 循环结束后,输出“老韩开心的嘴角微微上扬!”。
这种方法确保了只要用户输入的不是"y"
,循环就会继续执行。
运行结果:
老韩生气的使出闪电五连鞭
还不钱吗?回答[y/n]:s
老韩生气的使出闪电五连鞭
还不钱吗?回答[y/n]:s
老韩生气的使出闪电五连鞭
还不钱吗?回答[y/n]:s
老韩生气的使出闪电五连鞭
还不钱吗?回答[y/n]:d
老韩生气的使出闪电五连鞭
还不钱吗?回答[y/n]:g
老韩生气的使出闪电五连鞭
还不钱吗?回答[y/n]:h
老韩生气的使出闪电五连鞭
还不钱吗?回答[y/n]:y
老韩开心的嘴角微微上扬!