.
Java基础学习系列
1.“Java程序设计概述”篇
2.“Java基本程序设计结构” (一)篇
3."Java基本程序设计结构" (二)篇(本文)4.持续更新~
目录
一、字符串
1.字符串类String
有两种方法创建它的对象;
1)直接赋值
2) new一个String类型
对于这两种创建内存和性能上面存在差异
public class StringDemo {
public static void main(String[] args) {0
String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2);
}
}
JVM会去字符串常量池中去查找是否存在 ”abc“ 这个字符串,如果存在,则直接返回其在字符串常量池中的的地址;如果不存在,则是先创建这个字符串然后在把内存地址返回给对象变量。
这个打印出来的结果是true,比较字符串相等需要两个条件,一个是内存地址一样,一个是序列也一样
第二种,来看下面代码:
public class StringDemo {
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1 == str2);
}
}
JVM在会去字符串常量池中去检查 “abc” 字符串是否存在,如果存在,JVM会直接在堆中去创建这个 “abc” 的对象并返回内存地址,如果没有,则会在字符串常量池中进行创建,然后再去堆中创建这个字符串的对象并返回内存地址
两个对象虽然都是”abc“,但是他们在堆中的内存地址不一样,所以他们不是同一个东西,这是长得像而已
下面这份图就是String类型的两种创建的过程图
public void main(String[] args){
String str1 = "123";
String str2 = "245";
String str3 = new String("123");
String ste4 = new String("245");
String str5 = new String("678");
}
总结:
每次使用String类的时候,JVM都会去字符串常量池中去寻找有没有这个变量,这为创建字符串省去了不少时间,存在直接用就好,不仅提升了性能,还节省了内存。
2.不可变字符串
字符串在字符串常量池中不会发生变化。当对字符串进行拼接、裁剪、增加时,JVM会去池子里面去找有没有,有就不增加这个新的字符串,反之则增加。
public static void main(String[] args){
String str = "abcdesg";
str = str.substring(0,3) + "p";
}
上面这段代码 ,就是创建了一个新的字符串,“abcdefg”依旧存在于池子中
Java中的String虽然没有修改字符串的方法,但是提供了StringBuilder和
StringBuffer这两个类,前者线程安全但相对后者来说稍微慢一点,后者反之
3.字符串比较
由于变量保存的是字符串地址,所以直接用”==“ 的话,比较的其实就是地址,只有地址相等,才能返回true。
有时候,看起来两个长的一样的字符串之间 "==" 比较,不一定返回true,因为地址不一定一样(如下)
public static void main(String[] args){
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str1 == str2);
}
//返回false
得使用String的equals(String)方法
public static void main(String[] args){
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str1.equals(str2));
}
equals()底层代码
4.空串和null串
str1是只有 ”“ 的一个字符串,它的长度为0
str2引用的地址是一个空地址
String str1 = "";
String str2 = null;
”“字符串可以调用String类的方法,但是null不行,它会报出异常
判断这个字符串既不是空串也不是null,这个时候就可以使用下面这个代码:
if(str1 != null && !str1.equals("")){
........
}
二、输入输出
1.Scanner
如果你要实现键盘输入,就得用下面这行代码,创建输入对象
Scanner in = new Scanner(System.in);
Scanner类是用来进行输入操作的,它不仅可以实现键盘输入,还能从文件中把问内容读到这个对象中存储,以下面代码为例子:
//myNumbers 存储的是浮点数
Scanner sc = new Scanner(new File("myNumbers"));
while (sc.hasNextLong()) {
long aLong = sc.nextLong();
}
Scanner类内部提供的方法,next()和nextInt()、nextLong()、nextDoulde()都不能读取到带空格的输入,它们都对把空格、Tab键、Enter视为结束符,并会把除去Enter键,但是空格,Tab键不会,它们会被放在缓冲区。
除此之外的nextLine()方法,它只把Enter视为结束符,其他的它都来者不拒。
利用nextLine()来清除缓冲区
//代码一
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int i = in.nextInt();
String j = in.nextLine();
System.out.println(i + j);
}
//代码二
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int i = in.nextInt();
in.nextLine();
String j = in.nextLine();
System.out.println(i + j);
}
三、控制流程
1. 分支结构
1)if语句
//版本一
if(布尔表达式){
//条件满足时执行代码
}
//版本二
//else 意为否则
if(布尔表达式){
//条件满足时执行代码
}else{
//条件不满足时执行代码
}
if(布尔表达式){
//条件满足时执行代码
}else if(布尔表达式){
//条件满足时执行代码
}else{
//条件都不满足时执行代码
}
2)switch语句
switch(整数|枚举|字符|字符串){
case 内容1 : {
内容满足时执行语句;
break;
}
case 内容2 : {
内容满足时执行语句;
break;
}
...
default:{
内容都不满足时执行语句;
break;
}
}
2. 循环体
1)for循环
for(表达式1;表达式2;表达式3){
循环体;
}
//表达式1: 用于初始化循环变量
//表达式2: 循环条件
//表达式3: 更新循环变量
//例子
for (int i = 1; i <= 10; i++) {
System.out.println(i);
}
2)while循环
while(循环条件){
循环语句;
}
//例子
int num = 1;
while (num <= 10); {
System.out.println(num);
num++;
}
3)do while循环
do{
循环语句;
}while(循环条件);
//例子
int num = 1;
do {
System.out.println(num);
num++;
} while (num <= 10)
4)注意事项
1. do while 循环最后的分号不要忘记2. 一般 do while 很少用到 , 更推荐使用 for 和 while.
3. 中断控制流程
1)break
break 的功能是让循环提前结束.
int num = 100;
while (num <= 200) {
if (num % 3 == 0) {
System.out.println("找到了 3 的倍数, 为:" + num);
break;
}
num++;
}
2) continue
continue 的功能是跳过这次循环 , 立即进入下次循环 .
int num = 100;
while (num <= 200) {
if (num % 3 != 0) {
num++; // 这里的 ++ 不要忘记! 否则会死循环.
continue;
}
System.out.println("找到了 3 的倍数, 为:" + num);
num++;
}
四、大数类
如果基本的整数和浮点数精度不能够满足需求,那么可以使用Java.math包中的两个大数类DigInteger和DigDecimal。
这两个类可以处理包含任意长度数字序列的数值。BigInteger实现任意精度的整数运算,BigDecimal实现任意精度的浮点数运算。
使用静态的valueOf方法可以将普通的数值转化为大数类:
BigInteget.valueOf("1024");
对于更大的数,可以使用带字符串参数的构造器来进行创建对象
BigInteget i = new BigInteget("1321345646546464978464346549845613165494");
大数类的加减乘除得调用自己内部写好的方法才可以(非静态)
下面几个方法,分别对应加减乘除
i.add(BigInteger.valueOf(1))
i.subtract(BigInteger.valueOf(1))
i.mutiply(BigInteger.valueOf(1))
i.divide(BigInteger.valueOf(1))
五、数组
数组是一个数据结构,它是一对一的关系顺序表,它的值和下标都是对应的,只能通过下标来查询对应数据。
1.数组的创建
创建需要先规定类型,类型后面加一个 " [ ] " 这个括号来规定这是数组。(这里指的是一维数组)创建数组有两种方法
第一种
int[] arr = new int[10];
这种创建需要具体规定数组大小
第二种
int [] arr = { 0,1,2,3,4,5,6,7};
这种创建,程序会帮自己计算多长的数组来存储这一串花括号引起来的数据
一个数组的边界是[0,长度),左闭右开区间,不能越界,Java里面,越界它会报越界异常:
java.lang.ArrayIndexOutOfBoundsException当出现这个语句时,你就得检查一下越界问题。
public static void main(String[] args) {
int[] arr = new int[8];
arr[8] = 9;
}
上面代码的arr[8]已经触碰到底线了,程序自然就不乐意了,之接报错。
2.二维数组
对于多维数组,Java中更好的说法是:数组的数组.....,无线套娃,但这样看的话,其实也就是一个一维数组
看我下面的这张图:
这个是二维数组的示意图,这个就解释了,“数组的数组”是什么意思,第一层的每个位置都存放着一个数组,就这样套娃就构成了一个二维数组,多维数组也就是以此类推。
3.数组的拷贝
数组变量存储的是内存地址
Java允许一个数组变量拷贝到另一个数组变量。这时涉及到一个浅拷贝深拷贝的内容,感兴趣可以去查一查。如果这样做,两个变量拿到的都是同一个内存地址,引用的是同一个东西。