Java基本程序设计2

目录

一, 输入与输出

1.1 输入:

 1.2 输出:

二, 控制流

2.1 条件语句:

2.2 switch 语句

2.3 循环语句

2.4 中断控制流语句:

三 数组

3.1 创建数组

3.2 使用数组

3.3 数组的排序:

3.4 数组拷贝与引用的区别:

3.5 二维数组:

 四, String类

4.1 创建字符串

4.2 字符串比较相等

4.3 理解字符串不可变

4.4 字符串常量池

4.5 StringBuilder类 与 StringBuffer类

 4.6 StringBuilder类 与 StringBuffer类的区别


一, 输入与输出

1.1 输入:

  • Scanner in=new scanner(System.in):创造从控制台输入的标准输入对象
  • Scanner in=new scanner(String):in对象只能读String的内容
  • Scanner in=new scanner(new File("文件路径+文件名")):in对象读入文件中的内容

常用方法:

  • boolean hasNext():检测输入中是否还有其他单词
  • boolean hasNextInt():检测输入中是否还有整数
  • boolean hasNextDouble():检测输入中是否还有整数或浮点数

举例:

备注: 注意先输入nextInt(), 后输入nextLine的陷阱:

 1.2 输出:

System.out.println(msg);         // 输出一个字符串, 带换行
System.out.print(msg);           // 输出一个字符串, 不带换行
System.out.printf(format, msg);  // 格式化输出
printf的格式化输出:
转换符
类型
举例
输出
d
十进制整数
printf("%d", 100)
100
s
字符串
printf("%s", "abc")
abc
c
字符
printf("%c", ‘a’)        a
f
定点浮点数
printf("%f", 100f)
100.000000

二, 控制流

2.1 条件语句:

基本语法1:

if(布尔表达式){
    //条件满足时执行代码
}

基本语法2:

if(布尔表达式){
    //条件满足时执行代码
}else{
    //条件不满足时执行代码
}

基本语法3:

if(布尔表达式){
    //条件满足时执行代码
}else if(布尔表达式){
    //条件满足时执行代码
}else{
    //条件都不满足时执行代码
}

2.2 switch 语句

switch(整数|枚举|字符|字符串){
 case 内容1 : 内容满足时执行语句;break;

 case 内容2 : 内容满足时执行语句;break;

 ...

 default:内容都不满足时执行语句;
}

例子:

int day = 1;
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; 
}

输出结果为: 星期一

备注: 没有break语句的话,case 1: 满足后,case 2,case 3等都会被执行。

2.3 循环语句

while循环:

while(循环条件){ 
    循环语句; 
}

do...while循环:

do{ 
    循环语句; 
}while(循环条件);

for循环:

for(表达式1;表达式2;表达式3){ 
    循环体; 
}
表达式1: 用于初始化循环变量.
表达式2: 循环条件
表达式3: 更新循环变量

foreach 循环:

for(数据类型 变量名:数组名) {
    需要执行的语句块;
}

2.4 中断控制流语句:

break:直接退出循环

continue:直接进入下一次循环,跳过本次循环continue语句之后剩余的语句 

带标签的break语句:

三 数组

什么是数组:数组本质上就是让我们能 "批量" 创建相同类型的变量.

3.1 创建数组

基本语法:
// 动态初始化 
数据类型[] 数组名称 = new 数据类型 [] { 初始化数据 }; 

// 静态初始化 
数据类型[] 数组名称 = { 初始化数据 };

//声明数组
数据类型[] 数组名称= new 数据类型[数组长度n];

如:

int[] arr = new int[]{1, 2, 3}; 
int[] arr = {1, 2, 3};
char[] arr = new char[10];

3.2 使用数组

通过下标使用:

int[] arr = {1, 2, 3}; 
// 获取数组长度 
System.out.println("length: " + arr.length); // 执行结果: length: 3 
// 访问数组中的元素 
System.out.println(arr[1]); // 执行结果: 2 
System.out.println(arr[0]); // 执行结果: 1 
arr[2] = 100; 
System.out.println(arr[2]); // 执行结果: 100
使用 for-each 遍历数组:
int[] arr = {1, 2, 3};
for (int x : arr) { 
    System.out.println(x); 
}
// 执行结果:
 1
 2
 3

3.3 数组的排序:

升序排序:

public class Bb {
    public static void main(String[] args) {
        int[] nums={3,6,9,2,5,8,1,4,7};
        Arrays.sort(nums);                        
        System.out.println(Arrays.toString(nums));\\输出:[1, 2, 3, 4, 5, 6, 7, 8, 9]   
    }
}

Arrays.sort():Java库函数,默认升序排序

Arrays.toString(nums): 返回指定数组的内容的字符串表示形式

重写排序,降序排序:(只适用于包装类对象)

3.4 数组拷贝与引用的区别:

引用:引用是指变量中存的不是值本身,而是存放着值所在的内存地址

int[] nums = {3, 6, 9, 2, 5, 8, 1, 4, 7};
int[] a = nums;
System.out.println(Arrays.toString(a));\\输出:[3, 6, 9, 2, 5, 8, 1, 4, 7]

拷贝:

int[] nums = {3, 6, 9, 2, 5, 8, 1, 4, 7};
int[] b = Arrays.copyOf(nums, nums.length);
System.out.println(Arrays.toString(b));   \\输出:[3, 6, 9, 2, 5, 8, 1, 4, 7]

 区别:

原因:(简单示意图)

3.5 二维数组:

解释: 二维数组本质上也就是一维数组 , 只不过每个元素又是一个一维数组
基本语法 :
数据类型[][] 数组名称 = new 数据类型 [行数][列数] { 初始化数据 }

示例 :

int[][] arr = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
for (int row = 0; row < arr.length; row++) { 
    for (int col = 0; col < arr[row].length; col++) { 
        System.out.printf("%d\t", arr[row][col]); 
    }    
    System.out.println(""); 
}    
// 执行结果 :
    1 2 3 4 
    5 6 7 8 
    9 10 11 1

理解:

 四, String类

4.1 创建字符串

// 方式一
String str = "Hello Bit";
// 方式二
String str2 = new String("Hello Bit");
// 方式三
char[] array = {'a', 'b', 'c'};
String str3 = new String(array);
  • "hello" 这样的字符串字面值常量, 类型也是 String.
  • String 也是引用类型. String str = "Hello"; 这样的代码内存布局如下

 假设String str2=str,那么str2="world",str是不是也等于"world"呢?

结果:

 原因:

        事实上, str1 = "world" 这样的代码并不算 "修改" 字符串, 而是让 str1 这个引用指向了一个新的 String 对象

4.2 字符串比较相等

回顾一下int类型我们怎么比较的:

int x = 10 ;
int y = 10 ;
System.out.println(x == y);\\输出: true

那么String呢? 用以上方式试试:

        乍一看是对的,实际上这样比较是错误的,原因是因为String是引用类型,他们比较的是str1与str2中地址是否相同,而碰巧,他们是相同的:

        比较结果是str1和str2的值都为0x333,所以相同。而实际上我们想比较的是引用所指向的内容,即"hello"是不是等于"hello",接下来看这一段代码:

 原因:

str2中的值为0x444 不等于 str1中的值,因此两者不相等

        因此,在Java中,比较对象所引用的值不能简单的用==来比较, 而是要用到一些相关的方法,如String类中的equals方法

如:

使用注意事项: 方式二更合适, 因为当str=null时,方式一会出现异常

// 方式一
System.out.println(str.equals("Hello"));
// 方式二
System.out.println("Hello".equals(str));

4.3 理解字符串不可变

我们来看一下String类的原码:

 String类的一个成员变量是一个char类型的数组,并且被final修饰,表示value数组内容不可变 

那下面这段代码如何实训的呢?

String str="hello";
str+="!!!";
System.out.println(str);  //输出: hello!!!

我们来看一下编译时,他是如何运行的:

        从中我们可以看到,在拼接字符串的时候,是new了一个StringBuilder类,通过append()方法来将"hello"和"!!!"进行拼接,最后通过toStirng()方法转化为字符串,最后赋值给str引用 

在内存图中,是这样的:

4.4 字符串常量池

在上述例子中:

String str1 = new String("hello") ; 
String str2 = "hello" ;
String str3 = "hello" ;    
System.out.println(str1 == str2);   //输出: false
System.out.println(str2 == str3);   //输出: true

为什么str1!=str2,而str2==str3呢? 

String 类的设计使用了 共享设计模式
因为在 JVM 底层实际上会自动维护一个对象池(字符串常量池 )
  • 如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存 到这个对象池之中.
  • 如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用
  • 如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用

原因如图:

 通过调试,我们可以验证value引用指向的是同一个0x123的字符串地址

要注意的是:

String str1 = new String("hello") ; //匿名对象,不在字符串常量池中
String str2 = "hello" ;             //在字符串常量池中
System.out.println(str1 == str2);   //输出结果为false;

我们可以通过intern()方法来将方法来将 str1的匿名对象加入到字符串常量池中:

String str1 = new String("hello").intern() ;  //加入到字符串常量池
String str2 = "hello" ;                       //使用字符串常量池中的地址 
System.out.println(str1 == str2);             //输出true
面试题:请解释 String 类中两种对象实例化的区别
1. 直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。
2. 构造方法:会开辟两块堆内存空间,不会自动保存在对象池中,可以使用 intern() 方法手工入池。

4.5 StringBuilder类 与 StringBuffer类

        前面我们解释String类是不能改变的, 只有通过StringBuilder和StringBuffer类才能进行拼接, 而直接拼接String类会,底层编译会帮我们自动new一个StringBulider类进行拼接

这段代码:

String str="hello";
str+="!!!";

等价于:

        因此,但需要大量拼接字符串时,建议使用StringBuilder类 与 StringBuffer类, 这样减少创建这两个类是时间消耗。

验证:用String拼接10万次"a"与StringBuilder拼接10万次"a"分别需要的时间:

而且, StringBuilder类 与 StringBuffer类有String没有的方法:

 4.6 StringBuilder类 与 StringBuffer类的区别

主要区别体现在原码上:

        方法上,几乎一样,但StringBuffer是线程安全的,StringBuilder不是线程安全,但运行更快。synchronized 表示线程安全。

最后:class类名的首字母建议大写,截图有不当之处,望周知!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值