目录
练习3:使用if...else进行两个引用类型变量的判断(真正的判断两个变
练习:从键盘获取一个数(以int类型为例),根据输入的数值使用switch...case进行多重判断
练习2:break语句在switch...case多重条件判断中的使用例子
1.三元运算符(问号表达式)
基本形式
表达式 ? 表达式为真时进行的操作 : 表达式为假时进行的操作
一些例子
public class 三元运算符 {
public static void main(String[] args) {
//1.第一种形式,表达式?返回值:返回值
int n = 100;
System.out.println(n > 100 ? n : -n);
//2.第二种形式,表达式?返回值:表达式
int x = 100;
System.out.println(x > 10 ? x : (1 / 0));//此处1/0并没有抛出异常,因为表达式的值是真,因此表达式为假时进行的操作部分会被忽略
//3.第三种形式,问号表达式的嵌套使用
System.out.println(10 > 1 ? (1 > 2 ? "1>2" : "1<2") : "10<1");
}
}
一些注意点
- 当进行判断的表达式的值为真时,表达式为假部分的操作不会发生(直接跳过该部分)。
- 当进行判断的表达式的值为假时,表达式为真部分的操作不会发生(直接跳过该部分)。
- 三元运算符实现的效果和if...else的条件判断效果是一样的,只是三元运算符可以只占用一行。
2.if...else判断
基本形式
if(表达式){
表达式为真时执行的代码段;
}
else{
表达式为假时执行的代码段;
}
可能用到的其他形式
//1.不需要对表达式值为假的部分进行操作,没有else部分
if(条件表达式){
条件表达式为真时的代码块
}
//2.对if...else进行嵌套使用,当然,各else部分可以没有
if(条件表达式1){
条件表达式1为真时的代码块
if(条件表达式2){
条件表达式2为真时的代码块
}
}
else{
条件表达式1为假时的代码块
if(条件表达式3){
条件表达式3为真时的代码块
}
else{
条件表达式3为假时的代码块
}
}
练习1:使用if...else判断两个值类型的变量是否相等
public class class1{
public static void main(String[] args){
int a1 = 1;//值类型1
int a2 = 2;//值类型2
if(a1 == a2){
System.out.println("相等");
}
else{
System.out.println("不相等");
}
}
}
tip:当两个变量都是值类型时,才可以使用==运算符判断两数是否相等。
练习2:使用if...else判断两个引用类型变量是否相等
public class class2{
public static void main(String[] args){
String s1 = "hello";
String s2 = "HELLO".toLowerCase();
if (s1 == s2) {
System.out.println("s1==s2");
} else {
System.out.println("s1!=s2");
}
}
}
tip:==运算符并不能判断两个引用类型的变量是否相等,例如上面例子中给出的两个String类型,使用==运算符只能判断两个变量的地址是否相等(因为==两边是字符串的名称,即字符串的首地址,因此使用==进行判断是没有问题的,只是在改情况下判断的是两个字符串的首地址,并不是我们需要的两个字符串的内容判断)。
public class class2{
public static void main(String[] args){
String s5 = "hello";
String s6 = "hello";
if (s5 == s6) {
System.out.println("s5==s6");
} else {
System.out.println("s5!=s6");
}
}
}
tip:在上面的代码中,在内存单元的某处存放有"hello"这一串字符,两个引用类型的变量s5和s6指向的都是"hello"所在的地址,因此s5和s6虽然是两个变量,但是在地址和内容上两者是完全相等的。
练习3:使用if...else进行两个引用类型变量的判断(真正的判断两个变
量的内容是否相等)
public class class3{
public static void main(String[] args){
String s3 = "hello";
String s4 = "HELLO".toLowerCase();
if (s3.equals(s4)) {
System.out.println("s3==s4");
} else {
System.out.println("s3!=s4");
}
}
}
tip:需要使用equals( )方法来判断两个引用类型变量在内容上是否相等。
tip:不可以使用==运算符来判断两个引用类型变量在内容上是否相等,只能判断两个变量在地址上是否相等。
3.switch...case进行多重判断
基本形式
switch(条件){
case 情况1:{情况1对应代码块}
case 情况2:{情况2对应代码块}
...
case 情况n:{情况n对应代码块}
default:{上述所有情况都不符合时的代码块}
}
练习:从键盘获取一个数(以int类型为例),根据输入的数值使用switch...case进行多重判断
import java.util.Scanner;
public class SWITCH多重判断 {
//根据某一个表达式的值,分别去执行不同的分支
public static void main(String[] args) {
int op;
Scanner scanner = new Scanner(System.in);
op = scanner.nextInt();
switch (op) {
case 1:
System.out.println("1");
break;
case 2:
System.out.println("2");
break;
case 3:
System.out.println("3");
break;
default:
System.out.println("END");
}
}
}
4.for循环
基本形式
for(循环初始条件;循环终止条件;末尾循环体)
{
循环体
}
tip:循环初始条件、循环终止条件、末尾循环体这三个部分,任一部分的内容都可以为空。
//没有循环初始条件
for(;循环终止条件;末尾循环体){
循环体
}
//没有循环终止条件
for(循环初始条件;;末尾循环体){
循环体
}
//没有末尾循环体
for(循环初始条件;循环终止条件;){
循环体
}
//循环初始条件、循环终止条件、末尾循环体都没有
for(;;){
循环体
}
练习1:使用for循环计算1+2+...+100的值
public class class1{
public static void main(String[] args){
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println(sum);
}
}
练习2:使用for循环计算数组元素的和
public class class1{
public static void main(String[] args){
int[] arr1 = new int[]{1, 2, 3, 4, 5};
int sum1 = 0;
for (int i = 0; i < arr1.length; i++) {
sum1 += arr1[i];
}
System.out.println(sum1);
}
}
练习3:使用foreach循环输出数组中的每一个元素
- foreach循环是一种for循环针对数组的简化写法。
- foreach循环可以很方便地遍历数组元素,但是无法获取数组元素的索引。
public class class1{
/*
foreach的基本形式(以一维数组为例)
for(数据类型 变量名:数组名){
循环体
}
因为获取的是数组中的每一个元素,因此数据类型要与数组中元素的数据类型相同。
*/
public static void main(String[] args){
int[] arr1 = {1, 2, 3, 4, 555, 223};
for (int i : arr1) {
System.out.println(i);
}
}
}
练习4:一个没有循环终止条件的for循环例子
public class class1{
public static void main(String[] args){
for (int i = 0; ; i++) {
System.out.println(i);
if (i == 5) {
break;
}
}
}
}
5.while循环
基本形式
while(表达式){
循环体(表达式为真时才执行)
}
练习:使用while循环计算1+2+...+100
public class class1{
public static void main(String[] args){
byte i = 1;
int sum = 0;
while (i <= 100) {
sum += i;
i++;
}
System.out.println(sum);
}
}
6.do...while循环
基本形式
do{
循环体
}while(条件表达式);
tip:在do...while循环中,首先执行循环体,执行完毕之后再对条件表达式进行判断,因此,和while循环不同,当条件表达式为假时,while循环会执行循环体0次,do...while循环会执行循环体1次。因此do...while循环永远会执行一次循环体。
练习:使用do...while循环控制输出
public class class1{
public static void main(String[] args){
//此处的循环体至少被执行了1次
int i = 0;
do {
System.out.println(i);
i++;
} while (i > 100);
}
}
7.两个控制语句----break和continue
break的作用
- 在循环流程控制中,break用于终止当前的循环,即如果在循环中触发了break,则当前循环的剩余部分以及之后所有的循环都不会执行。
- 在switch...case中,break用于终止其他所有的case和default语句。
- 一般与条件判断语句(if、switch...case)搭配使用。
continue的作用
- 在循环流程控制中,continue用于跳出当前循环,即如果触发了continue,则当前循环体剩余的语句都不会执行,直接执行末尾循环体并进入下一轮循环。
- 一般与条件判断语句(if)搭配使用。
练习1:break语句在for循环中的使用例子
public class class1{
public static void main(String[] args){
//当sum满足条件sum>100时,这一个for循环便会被终止,程序继续执行for循环的下一条语句
int sum = 0;
for (int i = 0; ; i++) {
sum += i;
if (sum > 100) break;
}
System.out.println(sum);
}
}
练习2:break语句在switch...case多重条件判断中的使用例子
public class class1{
public static void main(String[] args){
int op;
Scanner scanner = new Scanner(System.in);
op = scanner.nextInt();
switch (op) {
case 1:
System.out.println("1");
break;//这个break使得程序执行到此处不会继续执行case 2、case 3、default
case 2:
System.out.println("2");
break;//这个break使得程序执行到此处不会继续执行case 3、default
case 3:
System.out.println("3");
break;//这个break使得程序执行到此处不会继续执行default
default:
System.out.println("END");
}
}
}
练习3:使用continue语句在for循环中的使用例子
public class class1{
public static void main(String[] args){
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) continue;//当触发continue时,程序会跳过循环体的剩余部分,直接执行末尾循环体(即i++),并进入下一轮循环。
//因此从功能上看,该循环输出的都是奇数
System.out.println(i);
}
}
}
8.无限循环(死循环)
无限循环
无限循环,又称为死循环,代表的是在循环类语句中,用于循环判断的表达式的值永远是真的,这就使得程序会永无止尽地执行下去,对CPU资源造成巨大的开销。
一个无限循环的例子
public class class1{
public static void main(String[] args){
while(true){
System.out.printf("true\n");
}
}
}
- 这是一个十分经典的死循环,程序会一直不断地在屏幕中打印true。
- 通常情况下,在程序中出现死循环是十分致命的错误,因此在编写程序时需要十分谨慎,谨防死循环出现。
- 但是,在某些特殊的情况下,死循环是十分有用的,在这种情况下,循环体中需要出现一些条件判断语句来对整个循环进行控制,否则也会引起致命错误。
一个看起来是死循环但实际上并不是死循环的例子
有如下的程序段
public class class1{
public static void main(String[] args){
byte i = 1;
while (i > 0) {
System.out.println(i);
i++;
}
}
}
表面上看起来,这是一个死循环,因为i的初值为1,并且i处于不断自增的状况,i>0永远是成立的。但是,请不要忽视一点:所有的数值型数据类型都是有表示范围的。在此处,i为byte类型,占用1字节,所能表示的最大值为127,当超过最大值后,溢出,i为一个负值,因此该循环会在此时自动结束。
9.字符类型
对字符型变量的操作
public class class1{
public static void main(String[] args){
//字符类型(基本的数据类型)
//java使用Unicode来表示字符
char c1='a';
char c2='中';
System.out.println(c1);
System.out.println(c2);
//要显示一个字符的Unicode编码,只需要直接将char类型赋值给int类型
int a1='a';
int a2='中';
System.out.println(a1);
System.out.println(a2);
//还可以使用转义符表示一个字符
char c3='\u0002';
char c4='\u0003';
System.out.println(c3);
System.out.println(c4);
}
}
一些常用的转义字符
转义字符 | 表示的含义 |
\" | " |
\' | ' |
\\ | \ |
\r | 回车符 |
\n | 换行符 |
\t | 水平制表符(Tab) |
\b | 退格符 |
\f | 反斜杠(\) |
\v | 垂直制表符 |
10.字符串类型
public class class1{
public static void main(String[] args){
//字符串类型(是一个引用类型)
String s1="";
String s2="中";
String s3="ABC";
String s4="中文 acd";
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s4);
//字符串的长度
System.out.println(s1.length());
System.out.println(s2.length());
System.out.println(s3.length());
System.out.println(s4.length());
//转义字符
String s5="abc\"aaa";
System.out.println(s5);
String s6="abc\\aaa";
System.out.println(s6);
//使用+来连接字符串
String s7="Hello";
String s8="World";
String s9=s7 + "" + s8;
System.out.println(s9);
//+还可以将不同的数据类型连接成字符串
String s10="age:";
int a3=20;
String s11=s10 + a3;
System.out.println(s11);
//字符串的不可变性
String s12="hello";
s12="hello1";//之前的hello仍然存在,只是现在无法通过s12变量来访问
System.out.println(s12);
//字符串类型可以指向一个空值NULL
String s13=null;
System.out.println(s13);
}
}
11.输入输出
输入
import java.util.Scanner;
public class class1{
public static void main(String[] args){
//1.首先创建一个Scanner对象
Scanner scanner = new Scanner(System.in);
//2.获取输入流中的内容,并赋值给变量
//需要注意的是,有多种方法获取输入流,不同的方法适用于不同的变量类型
//对于int类型
int num = scanner.nextInt();
//对于String类型
String name = scanner.next();
String name1 = scanner.nextLine();
//上面两种方法都是适用于String类型的,区别在于
//第一种方法只能将输入流中的一个单词赋值给变量,即遇到空格便停止
//第二种方法会将输入流中的整行赋值给变量,即遇到回车符才停止
//3.关闭Scanner对象
scanner.close();
}
}
输出
- 使用println( )方法进行输出
public class class1{ public static void main(String[] args){ System.out.println("aaa"); } }
- 使用printf( )方法进行格式化输出
public class class1{ public static void main(String[] args){ int x = 100; System.out.printf("%d", x); } }
tip:其中的%d为格式化控制符,表示以十进制整数的格式输出。
12.数组
对一维数组的创建以及赋值
public class class1{
public static void main(String[] args){
//这是一个整型数组
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
//这是一个浮点型数组
float[] arr1 = {1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f};
//这是一个字符串数组
String[] arr2 = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"};
//第二种创建数组的方法,这边以整型数组为例
//即先数组,再对数组中的每一个元素进行赋值
int[] arr3 = new int[3];
arr3[0] = 1;
arr3[1] = 2;
arr3[2] = 3;
//数组也是一种引用数据类型,和String相似
int[] arr4 = new int[]{1, 2, 3, 4};
System.out.println(arr4.length);
System.out.println(arr4);
arr4 = new int[]{5, 6, 7};//重新赋值后,之前的内容仍然存在
System.out.println(arr4.length);
System.out.println(arr4);//两处arr4的地址是不相等的
}
}
对多维数组的定义和输出(以二维数组为例)
import java.util.Arrays;
public class class1{
public static void main(String[] args){
//二维数组
//1.定义一个二维数组
//第一种定义方式
int[][] arr1 = {{1, 2, 3}, {2, 2, 2}};//2行3列的二维数组
//第二种定义方式
int[][] arr2 = new int[2][3];
arr2[0][0] = 1;
arr2[0][1] = 2;
arr2[0][2] = 3;
arr2[1][0] = 2;
arr2[1][1] = 2;
arr2[1][2] = 2;
//2.访问一个二维数组的某一个元素
System.out.println(arr1[0][1]);//访问第一行的第二个元素
//二维数组中每一维的长度不是一定要相等的
int[][] arr3 = {{1, 2, 3}, {2, 2}, {1, 3, 4, 4}};
System.out.println(arr3[0].length);
System.out.println(arr3[1].length);
System.out.println(arr3[2].length);
//使用双重循环遍历二维数组
for (int[] num1 : arr3) {
for (int num2 : num1) {
System.out.println(num2);
}
}
//直接使用java类库输出二维数组
System.out.println(Arrays.deepToString(arr3));
}
}
数组的遍历操作
import java.util.Arrays;
public class class1{
public static void main(String[] args){
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
//1.使用标准for循环遍历数组
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
//2.使用for...each循环遍历数组
for (int n : arr) {
System.out.print(n + " ");
}
System.out.println();
//3.直接使用java类库打印数组的内容
System.out.println(Arrays.toString(arr));
}
}
使用冒泡排序方法对一维数组进行排序
import java.util.Arrays;
public class class1{
public static void main(String[] args){
//生成一个int类型的乱序数组
int[] arr = new int[10];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * 100);
}
System.out.println(Arrays.toString(arr));
//排序(这边使用冒泡排序)
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
使用选择排序方法对一维数组进行排序
import java.util.Arrays;
public class class1{
public static void main(String[] args){
//生成一个int类型的乱序数组
int[] arr = new int[10];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * 100);
}
System.out.println(Arrays.toString(arr));
//排序(选择排序)
//在每一轮排序中,将最值与第一个位置的数交换
for (int i = 0; i < arr.length; i++) {
int max = i;//标记最大值
//寻找剩余序列中的最大值,并记录其下标
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] > arr[max]) {
max = j;
}
}
//将最大值与第一个位置的数交换
//当最值的位置没有变化时,不用交换
if (max != i) {
int temp = arr[i];
arr[i] = arr[max];
arr[max] = temp;
}
}
System.out.println(Arrays.toString(arr));
}
}
13.递归
什么是递归
递归由两部分组成,一部分是定义递归,即需要指出什么时候结束递归调用;另一部分是递归体,即进行递归时需要执行哪些操作。
说的简单一些,递归某一个函数,自己调用自己。
一个简单的递归例子:计算n!
public class class1{
public static void main(String[] args){
long time_start = System.currentTimeMillis();
System.out.println(factorial(39));
long time_end = System.currentTimeMillis();
System.out.println("递归消耗的时间:" + (time_end - time_start));
}
public static long factorial(int n) {
//递归头,递归的结束条件
if (n == 1) {
return 1;
}
else{
//相当于计算公式n! = n * (n-1)!
return n * factorial(n - 1);
}
}
}
递归的使用注意事项
有时候使用递归的思想解决问题确实十分的方便,例如二叉树的遍历和构造。但是递归会使用到栈,深层次的递归会大量使用栈,而用户栈的空间并不是非常巨大,因此递归虽然方便但是效率很低。
因此,在最求高性能的情况下,尽可能地不要使用递归的方法,因为递归对时间和空间的开销都十分的巨大。