Java基础1
Getting Started
Anatomy of a Java Program
Java的 函数 我们常常把第一个花括号与函数声明放在一行。但是C,C#常常是另起一行
1 | void sendEmail(){ |
每一个Java程序都必须有一个main函数,也就是主函数
1 | void main(){ |
Java中,这些函数不会单独存在,他们都在类里面。当函数放在类中时,我们称其为类的方法。在Java中,类和方法都应该具有访问修饰符(access modifier),访问修饰符是private,public之类的.
在Java中,我们用不同的方法来命名我们的类和我们的方法。
PascalNamingConvention : 用于类命名。特征就是每个单词首字母大写
camelNamingComvention: 用于方法命名,也就是驼峰命名法
1 | public class Main{ |
Your First Java Program
package com.company 代表着这个类所属的包
这个包下面有Main类,类中有一个静态的main方法
我们现在输出Hello World
在这里使用系统类 System ; System.out 是一个PrintStream 类型,也就是输出字符串的。然后在System.out中我们运用 printIn方法,他是printLine的缩写。点击运行,我们即可看到终端打印Hello World了
1 | package com.company; |
How Java Code Gets Executed
当我们跑Java程序的时候,是怎么运作的。
在编译步骤中,Intellij 使用Java编译器把代码编译成Java bytecode的形式。编译完成后,Java bytecode可以在Windows ,Mac,Linux或任何有JRE(Java runtime environment)的操作系统上运行。 JRE中各个操作系统都有一个软件叫做JVM(Java Virtual Machine) .JVM 会把Java byte code 转换成 Windows可以理解并架构的Native Code。这就是所谓的 一次编译,到处运行
java有4个版本:Java SE,Java EE,Java ME ,Java Card
Java SE 是Java Standard Edition的缩写,这是Java的核心平台,包含了Java的每一个库
Java EE 是Java Enterprise Edition的缩写,用于构建超大型、分布式系统。它建立在SE之上
Java ME是Java Micro Edition的缩写,这是专门为移动设备设计的Java标准版的子集
Java Card是在智能卡中使用的
Types
Primitive Types
Primitive Types是存储simple value的,也就是下面的八种基本类型
Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。
byte:
- byte数据类型是8位、有符号的,以二进制补码表示的整数;
- 最小值是-128$(-2^7)$;
- 最大值是127$(2^7-1)$;
- 默认值是0;
- byte类型用在大型数组中节约空间,主要代替整数,因为byte变量占用的空间只有int类型的四分之一;
- 例子:byte a = 100,byte b = -50。
short:
- short数据类型是16位、有符号的以二进制补码表示的整数
- 最小值是-32768$(-2^{15})$;
- 最大值是32767 $(2^{15} - 1)$;
- Short数据类型也可以像byte那样节省空间。一个short变量是int型变量所占空间的二分之一;
- 默认值是0;
- 例子:short s = 1000,short r = -20000。
int:
- int数据类型是32位、有符号的以二进制补码表示的整数;
- 最小值是-2,147,483,648 $(-2^{31})$;
- 最大值是2,147,483,647 $(2^{31} - 1)$;
- 一般地整型变量默认为int类型;
- 默认值是0;
- 例子:int a = 100000, int b = -200000。
long:
- long数据类型是64位、有符号的以二进制补码表示的整数;
- 最小值是-9,223,372,036,854,775,808 $(-2^{63})$;
- 最大值是9,223,372,036,854,775,807 $(2^{63} -1)$;
- 这种类型主要使用在需要比较大整数的系统上;
- 默认值是0L;
- 例子:
1 | long viewsCount = 3_123_456_789L; |
float:
- float数据类型是单精度、32位、符合IEEE 754标准的浮点数;
- float在储存大型浮点数组的时候可节省内存空间;
- 默认值是0.0f;
- 浮点数不能用来表示精确的值,如货币;
- 例子:
1 | float f1 = 234.5F; |
double:
- double数据类型是双精度、64位、符合IEEE 754标准的浮点数;
- 浮点数的默认类型为double类型;
- double类型同样不能表示精确的值,如货币;
- 默认值是0.0d;
- 例子:double d1 = 123.4。
boolean:
- boolean数据类型表示一位的信息;
- 只有两个取值:true和false;
- 这种类型只作为一种标志来记录true/false情况;
- 默认值是false;
- 例子:boolean one = true。
char:
- char类型是一个单一的16位Unicode字符;
- 最小值是’\u0000’(即为0);
- 最大值是’\uffff’(即为65,535);
- char数据类型可以储存任何字符;
- 例子:char letter = ‘A’。
Reference Types
Reference Types是存储复杂的对象的 ,比如说Date类 ,mail message 类
在使用Reference Types 时,我们必须手动分配内存
1 | package com.company; |
Primitive vs Reference Types
Primitive Types 中,我们声明两个变量,让他们相等,那么只是数值上相等,它们的存储地址是不一样的
但是Reference Types ,里面存储的时地址,所以让 point2 = point1之后,point1,point2中存储的有相同的地址。当对point1中修改时,point2也会相应修改。
1 | package com.company; |
Strings
在java当中,我们String是一个 Reference Type
,但是我们使用 String 不需要引入Java的库,也不需要用new来声明(用new也可以,只是简便声明不需要使用new Sring)
我们也可以通过加号直接连接两个字符串。
因为字符串是 Reference Type
,所以我们可以通过 . 来使用String类中的方法
区分arguments
和 parameter
: parameter
可以理解为占位符,只是申请了一段空间的容器。但是arguments
是我们传入的值
endsWith()
用来判断字符串是否以某一字符串结束的
startsWith()
用来判断字符串是否以某一字符串开始的
length()
计算字符串的长度
indexOf()
计算目标字符串第一个字符在查询字符串中的索引,如果不是该查询字符串的子串,那么返回-1
replace()
是替换,前一个参数是被替换的字符串;后一个参数是需要替换进去的字符串
toLowerCase()
和toUpperCase()
是让字符串全部变小写或者大写
trim()
是让字符串去掉头尾的空格,这在用户输入一些
1 | package com.company; |
Escape Sequences 转义序列
双引号的转义 就是 \"
反斜杠的转义就是 \\
换行的转义就是 \n
1 | package com.company; |
Arrays
用繁琐且老旧的语法来声明一个数组的语法是这样的:
1 | public class Main { |
当我们提前知道了数组中的元素的时候,我们可以更简单的声明一个数组
用花括号声明即可
1 | public class Main { |
我们不能直接 System.out.printIn(number)
因为这样java引擎会根据每个数字存储的地址计算得出一个我们看不懂的字符串。所以需要System.out.println(Arrays.toString(numbers));
Multi-dimensional Arrays
我们可以定义多维数组,但是多维数组需要deepToString()
而不是 toString()
才能正常打印
1 | public static void main(String[] args) { |
1 | public static void main(String[] args) { |
Constants 常量(final关键词)
我们想定义 pi为常量,所以我们希望它一经申明就不能再改变,我们需要用final
来声明一个常量。常量的所有字母需要大写。
1 | public class Main { |
此外,final还可以用来修室类和方法。浅谈Java中的final关键字 - 平凡希 - 博客园 (cnblogs.com)
当用final修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用final进行修饰。final类中的成员变量可以根据需要设为final,但是要注意final类中的所有成员方法都会被隐式地指定为final方法。在使用final修饰类的时候,要注意谨慎选择,除非这个类真的在以后不会用来继承或者出于安全的考虑,尽量不要将类设计为final类。
如果只有在想明确禁止 该方法在子类中被覆盖的情况下才将方法设置为final的。即父类的final方法是不能被子类所覆盖的,也就是说子类是不能够存在和父类一模一样的方法的。
Arithmetic Expressions
和C++一样,不讲了
Order of Operations
和C++一样,不讲了
Casting
java中的类型转换
1 | short x = 1; |
我们这样会做一个隐式类型转换。short是短整型,int是整型。int中可以存储所有short变量当中的值
在java中,是这样操作隐式类型转换的 :在 int y = x+2 这句话中,java看见x,会在内存中某个地方申明一个匿名变量,那个匿名变量是整数,然后java将x的值复制到那个匿名变量中。再执行加法
1 | double x = 1.1; |
在整型、浮点数之间转换,java也会按照这个规则。 首先会把2 转换为2.0 ,其次执行加法
byte>short>int>long>float>double
java中的数据类型可以根据这个链转换。如果不丢失数据的话,都会发生隐式转换。
我们也可以进行强制类型转换,这时候会丢失一些数据
1 | double x = 1.1; |
现在,我们想把string 转为数字,无论用隐式转换还是显示转换都无法达成。需要引用一个类
用 Short.parseShort()
,Integer.parseInt()
,Double.parseDouble()
等来把字符串转换成整数、浮点数
注意: 如果 String x = "1.1"
那么转换成 整数的时候,就会发生报错
1 | String x = "1"; |
The Math Class
1 | int result = Math.round(1.1F); |
注意,我们不能 这样来得到一个0-100的随机整数:int result = (int) Math.random()*100;
因为Math.random()
产生一个0-1的小数,int转换之后变成0了,0*100 还是等于0,所以我们必须要把整个表达式包裹: int result = (int) (Math.random()*100);
Formatting Numbers
注意:NumberFormat
是一个抽象类,无法实例化,我们不能直接 NumberFormat currency = new NumberFormat()
我们需要用到NumberFormat
这个类。其中getCurrencyInstance
是把数字转换成钱币的格式,getPercentInstance
则是把数字转换成百分比的形式。
我们可以简单的使用NumberFormat.getCurrencyInstance().format()
来格式化字符串
1 | package com.company; |
Reading Input
要读取字符串或者数字,我们需要用到scanner
首先新建一个 Scanner对象,我们要确定信息是从终端获取的还是从文件当中获取的。我们这里是从终端获取的,所以选择 System.in
然后用scanner.nextByte()
读取一个byte 或者 scanner.nextline()
是读取一行信息,以此类推,有nextBoolean()
,nextDouble()
,nextFloat()
等等
因为System.out.println();
是打印一行信息, 我们希望 是 Age: 后输入年龄,不用换行。所以使用 System.out.print()
1 | package com.company; |
Project- Mortgage Calculator 按揭
等额本息公式: $P = L[c(1+c)^n]/[(1+c)^n-1] $
每月还款金额 = [贷款本金×月利率×(1+月利率)\^还款月数]÷[(1+月利率)\^还款月数-1]
其中 L 代表 principal,即本金
c 代表 monthly Interest ,月利率
n 代表 月数
相对于等额本金还款法 的劣势在于支出利息较多,还款初期利息占每月供款的大部分,随本金逐渐返还供款中本金比重增加。但该方法每月的还款额固定,可以有计划地控制家庭收入的支出,也便于每个家庭根据自己的收入情况,确定还贷能力。
最终计算得到的 Mortage就是每月需要支付的按揭金额
1 | package com.company; |
Control Flow
Comparison Operators
和C++一样
Logical Operators
在C中布尔变量用bool声明,但是在java中用 boolean声明,其他一样
||, &&,! 和C++一样
If Statements
和C++一样
The Ternary Operator
也就是 ?: 运算符,和C++一样
Switch Statements
1 | public class Main { |
Exercise- FizzBuzz
1 | package com.company; |
For Loops
和C++一样
While Loops
和C++一样
Do..While Loops
和C++一样
Break and Continue Statements
和C++一样
For-Each Loop
1 | package com.company; |
还是和C++一样
Project- Mortgage Calculator
1 | package com.company; |
Clean Coding
对上面的代码进行优化、重构
Creating Methods 新建方法
1 | package com.company; |
Extracting Methods
就像上面写的简单的方法一样,现在我们把计算Mortage写成一个方法:
1 | package com.company; |
Refactoring Repetitive Patterns
然后,我们继续把输入数字的语句抽象出来成为一个函数,readByte,readInt,readFloat
1 | package com.company; |
Project- Payment Schedule
计算每期付款后剩下需要还款余额
公式:$B =L[(1+c)^n-(1+c)^p]/[(1+c)^n-1]$
B 代表 Balance,即需要还款的余额
p代表当前还款进行到第几个月
1 | package com.company; |
我们可以利用idea自带的 Refactory->Extract->Method来自动生成方法十分方便。
Debugging and Deploying Applications
Types of Errors
Compile-time Errors Idea可以帮我们提示
Run-time Errors 可以通过Debugger来调试
Debugging Java Applications
https://www.bilibili.com/video/BV19J411t7dD?p=15