学习 Java 的一些笔记
注意事项
Java 对大小写很敏感
类名必须以字母开头, 后面可以跟字母和数字, 也可以用 _和 $ 两种符号. 不能使用 Java 保留字.(标准类名: 以大写字母开头, 如果类名由多个单词组成, 每个单词首字母应该要大写
源代码文件名必须与公共类的名字相同
为了代码能够你执行, 必须包含一个 main 方法
Java 中的三种注释
单行注释( // )
多行注释( /* */)
多行注释 可以自动生成文档( /** */)
数据类型
类型 | 储存需求 | 取值范围 | |
---|---|---|---|
boolean | 1 字节 (8 bit) | true, false | |
char | 2 字节 (16 bit) | 0 ~ 216-1 | |
byte | 整型 | 1 字节 (8 bit) | -128 ~ 127 |
short | 整型 | 2 字节 (16 bit) | -32 768 ~ 32 767 (-215 ~ 215-1) |
int | 整型 | 4 字节 (32 bit) | -2 147 483 648 ~ 2 147 483 647 (-231 ~ 231-1) |
long | 整型 | 8 字节 (64 bit) | -9 223 372 036 854 776 808 ~ 9 223 372 036 854 775 807 (-263 ~ 263-1) |
float | 浮点类型 | 4 字节 (32 bit) | 大约 ±3.402 823 47E + 38F(有效位数为 6~7 位) |
double | 浮点类型 | 8 字节 (64 bit) | 大约 ±1.797 693 134 862 315 70E + 308(有效位数为 15 位) |
长整数型有一个后缀 L (如 4000000000L)
十六进制数值有一个后缀 0x (如 0xCAFE)
八进制有一个前缀 0 (如 010)
二进制有一个前缀 0b (如 0b1001)
Float 类型的数值有一个后缀 F (如 3.14F)
final 关键字
final 关键字表示变量只能被赋值一次, 一旦被赋值后, 就不能被更改.
例如:
Final double CMCC = 2.54
如果希望某个常量可以在一个类中的多个方法中使用, 称这个常量为类常量. 可以使用关键字 static final 设置一个类常量, 定义的位置在 main 方法外部. 因此, 同一个类的其他方法中也可以使用这个常量. 如果一个常量被声明为 public, 那么其他类的方法也可以使用这个常量.
运算符
在 java 中, 算术运算符可以用 + - */ 来代表加减乘除.
当参与除 (/) 运算的两个操作数为整数时, 表示整数除法, 答案为整数. 否则, 表示浮点除法.
求余数可以用 %
例如 10%3 等于 1,10%3.0 等于 1.0
注意: 整数除以 0 将会产生一个异常, 而浮点数除以 0 将会得到无穷大或 NaN 结果.
i++ 和 ++i 的 区别
如果只是看 i++ 和 ++i, 这两个是等价的, 都等同于 i=i+1, 都是变量自身加 1.
在一般情况下, 它们都是跟赋值联系在一起.
比如:
- int a;
- a=i++; // 将 i 的值赋值给 a, 即 a=i; 然后再执行 i=i+1;
也就是[a=i++;] 与[a=i; i=i+1;] 等价.
a=++i;// 将 i+1 的值赋给 a, 即 a=i+1; 然后再执行 i=i+1;
也就是[a=++i;] 与[a=i+1;i=i+1;] 等价.
总结一下
前置 ++ 是将自身加 1 的值赋值给新变量, 同时自身也加 1;
后置 ++ 是将自身的值赋给新变量, 然后才自身加 1.
关系运算符
三元操作符
Condition? expression1: expression2
当 Condition 为 true 时, 计算或返回第一个表达式 expression1, 如果为 false, 则计算第二个表达式 expression2.
如 x <y ? x: y
返回 x 和 y 中较小的那个值.
数值类型之间的转换
整型, 实型(常量), 字符型数据可以混合运算. 运算中, 不同类型的数据先转化为同一类型, 然后进行运算. 转换过程中可能导致溢出或损失精度
低 ---------------------------------------------------------- 高
byte, short, char-> int -> long-> float -> double
自动类型转换
必须满足转换前的数据类型的位数要低于转换后的数据类型.
自动转换由低到高的顺序转换
- int n = 123456789;
- float f = n;//f 值为 1.234567892E8
当使用上面两个数值进行二元操作时(例如 n+f , n 是整数, f 是浮点数), 先要将两个操作数转换为同一种类型, 然后再进行计算.
如果两个操作数中有一个是 double 类型, 另一个操作数就会转换为 double 类型;
否则, 如果其中一个操作数是 float 类型, 另一个操作数将会转换为 float 类型;
否则, 如果其中一个操作数是 long 类型, 另一个操作数将会转换为 long 类型.
否则, 两个操作数都将被转换为 int 类型.
强制类型转换
高的向低的顺序转换
- double x = 3.94;
- int y = (int) x;
x 的结果为 3, 强制类型转换通过截断小数部分将浮点值转为整型.
如果想要四舍五入, 得到最接近的整数. 可以使用 Math.round 方法
- double x = 3.14;
- int y = (int) Math.round(x);
结果为 4, 当调用 round 时, 仍然需要使用强制类型转换(int). 其原理是因为 round 方法返回的结果为 long 类型. 由于存在信息丢失的可能性, 所以只有使用显式的强制类型转换才能够将 long 类型转换成 int 类型.
不要在 boolean 类型与任何类型之间进行强制类型转换, 这样可以防止发生错误.
运算符优先级
优先级 | 运算符 | 简介 | 结合性 |
---|---|---|---|
1 | [ ]、 .、 ( ) | 方法调用,属性获取 | 从左向右 |
2 | !、~、 ++、 -- | 一元运算符 | 从右向左 |
3 | * 、/ 、% | 乘、除、取模(余数) | 从左向右 |
4 | + 、 - | 加减法 | 从左向右 |
5 | <<、 >>、 >>> | 左位移、右位移、无符号右移 | 从左向右 |
6 | < 、<= 、>、 >=、 instanceof | 小于、小于等于、大于、大于等于,对象类型判断是否属于同类型 | 从左向右 |
7 | == 、!= | 2 个值是否相等,2 个值是否不等于。 下面有详细的解释 | 从左向右 |
8 | & | 按位与 | 从左向右 |
9 | ^ | 按位异或 | 从左向右 |
10 | | | 按位或 | 从左向右 |
11 | && | 短路与 | 从左向右 |
12 | || | 短路或 | 从左向右 |
13 | ?: | 条件运算符 | 从右向左 |
14 | =、 += 、-= 、*= 、/=、 %=、 &=、 |=、 ^=、 <、<= 、>、>= 、>>= | 混合赋值运算符 | 从右向左 |
字符串
子串 substring
String 类的 substring 方法可以从一个较大的字符串提取出一个子串.
substring(a,b)
a 表示开始的位置(从 0 开始计数)
b 表示不想复制的第一个位置
例如
- String greeting = "hello";
- String s = greeting.substring(0,3);
- // s = hel
- // 从 0 开始计数, 直到 3 位置, 但是不包括 3, 所以返回 hel
substring 的一个优点: 容易计算子串的长度, 长度为 b-a.
例如 hel 的长度为 3-0=3
检测字符串是否相等
可以使用 equals 来检测两个字符串是否相等.
s.equals(t)
如何相等, 会返回 true, 否则, 返回 false. s 和 t 可以是字符串变量, 也可以是字符串常量.
eg: "hello".equals(greeting)
检测是否相等, 而且不区分大小写, 可以使用 equalsIgnoreCase 方法.
eg: "hello".equalsIgnoreCase("HeLLO)
不能使用 == 运算符来检测两个字符串是否相同, 这个运算符只能够确定两个字符串是否放置在同一个位置.
空串和 Null 串
空串是一个 Java 对象, 有自己的串长度 (0) 和内容(空). 可以通过调用以下代码检查字符串是否为空.
if(str.length()==0)
或
if (str.equals(""))
null 表示目前没有任何对象与该变量关联. 可以通过调用以下代码检查字符串是否为 null
if (str == null)
要检测一个字符串既不是 null 也不是空串:
if (str != null && str.length()!=0)
length() 与 charAt()
length 方法会返回采用 UTF-16 编码表示的给定字符串所需的代码单元数量.
想要得到实际的长度, 即代码点数量, 可以调用
xxx.codePointCount(0,xxx.length())
调用 s.chatAt(n)将返回位置 n 的代码单元, n 介于 0~ s.length()-1 之间.
- eg:
- String greeting = "Hello"
- char first = greeting.charAt(0); // first is H
- char last = greeting.charAt(4); // last is o
想得到 i 个的代码点, 可以使用
- int index= greeting.offsetByCodePoints(0,i);
- int cp = greeting.codePonintAt(index);
输入输出
读取输入
为了能够读取用户在控制台的输入, 首先需要创建一个 Scanner 对象, 并与 "标准输入流"System.in 关联.
- Scanner in = new Scanner (System.in)
- next()
读取到输入有效的字符才会结束输入, 对于输入有效的字符之前的空白会自动去掉, 输入有效的字符之后的空白作为分隔符或者结束符. next() 不能得到带有空格的字符串.
nextLine()
以 enter 为结束符, nextLine()可以得到带有空格的字符串, 不会去掉空白, 会全盘输出.
nextInt()
得到 int 类型的数据. nextDouble(),nextFloat()以此类推.
boolean hasNext()
检测输入中是否有还有其他单词.
记得要 import java.util.*;
- import java.util.*;
- public class Input_and_Output {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- Scanner in = new Scanner(System.in);
- System.out.print("what is your name :");
- String name = in.nextLine();
- System.out.print("age :");
- int age = in.nextInt();
- System.out.println("the name is" + name + ",the age is"+age);
- }
- // 输入结果:
- //what is your name :jerry
- //age :24
- //the name is jerry,the age is 24
格式化输出
System.out.print(X)会将以 x 对应的数据类型所允许的最大非 0 数字位数打印输出 x
- double x = 10000.0/3.0;
- System.out.print(x); // x = 3333.3333333333335
为了能够方便格式输出结果, 可以使用 printf().
- double x = 10000.0/3.0;
- System.out.printf("8.2f",x);
- // x = 3333.33 使用 8 个字符的宽度和小数点后两位字符的精度打印 x
- // 因为小数点后 2 位, 为 3333.33. 但是指定要 8 个字符的宽度, 所以左边会补一个空格
- // x 结果为(1 个空格)3333.33
用于 printf 的转换符
转换符 | 类型 | 举例 |
---|---|---|
%s | 字符串类型 | "Hello" |
%c | 字符类型 | 'H' |
%b | 布尔类型 | true OR false |
%d | 整数类型(十进制) | 10 |
%x | 整数类型(十六进制) | 9f |
%o | 整数类型(八进制) | 237 |
%f | 浮点类型 | 15.9 |
%a | 十六进制浮点类型 | 0x1.fccdp3 |
%e | 指数类型 | 6.23e+24 |
%g | 通用浮点类型(f 和 e 类型中较短的) | 42.5000 |
%h | 散列码 | 42628b2 |
%% | 百分比类型 | % |
%n | 换行符 | 相当于 "\n" 换行作用 |
%tx | 日期与时间类型(x 代表不同的日期与时间转换符) | 见博文下表 |
大数值
如果基本的整数和浮点数精度不够满足需求, 那么可以使用 java.math 包中的两个很有用的类: BigInteger 和 BigDecimal. 这两个类可以处理包含任意长度数字序列的数值.
BigInteger 实现任意精度的整数运算
BigDecimal 实现任意精度的浮点数运算
把普通的数值转换成大数值, 可以使用静态的 function valueOf() { [native code] }方法
BigInteger a = BigInteger.function valueOf() { [native code] }(100)
大数值的运算不能使用常用的算术运算符 (如 +,*) 处理, 而是要使用大数值类中的 add 和 multiply
- BigInteger c = a.add(b); // c=a+b
- BigInteger d = c.multiply(b.add(BigInteger.function valueOf() {
- [native code]
- }(2))); // d = c*(b+2)
其他的运算包括有 subtract(减),divide(除)和 mod(余数)
数组
数组声明
数组是一种数据结构, 用来存储同一类型值的集合
数组声明方式:
int[] array 或者 int array[]
数组初始化
- int[] array = new int[100];
- int[] arry = new int[]{
- 1,2,3,4,5
- }
- int[] array = {
- 1,2,3,4,5
- }
创建一个数字数组时, 所有的元素都初始化为 0.
boolean 数组的元素会初始化为 false
对象数组的元素会初始化为一个特殊值 null
- public class Array {
- public static void main(String[] args) {
- int[] test = new int[5];
- for(int i =0;i<test.length;i++) {
- System.out.println(test[i]);}
- }
- }
输出的结果会是: 0 0 0 0 0
重要:
一旦创据数组, 就不能再改变数组的大小. 如果需要在运行中扩展数组的大小, 则需要使用另一种数据结构 -- 数组列表(array list)
for each 循环
Java 有一种很强的循环结构, 可以用来依次处理数组中的每个元素而不必为指定下标值而分心.
格式:
for(variable:collection) statement
定义一个变量用于暂存集合中的每一个元素, 并执行相应的语句.
collection 这一集合表达式必须必须是一个数组或者是一个实现了 Iterable 接口的类对象(例如 Arraylist).
- eg:
- for(int element :a)
- System.out.println(element)
- // 打印数组 a 的每一个元素, 一个元素占一行
- // for each element in a
数组拷贝
在 java 中, 允许将一个数组变量拷贝到给另一个数组变量. 这时, 两个变量将引用同一个数组
- int[] a = {
- 2,3,5,7,11,12
- };
- int[] b = a;
- a[5] = 12 // b[2] = 12
如果想将一个数组的所有值拷贝到一个新的数组去, 使用 Arrays 类的 copyTo 方法.
int[] copieda = Arrays.copyTo(a,a.length);
第二个参数是新数组的长度, 可以通过这个方法来增加数组的大小.
eg: Arrays.copyTo(a,2*a.length); 增加到 2 倍大
如果数组元素是数字数组时, 多余的元素都赋值为 0.
如果数组元素是 boolean 数组, 多余的元素会赋值为 false
如果数组元素是对象数组的元素, 多余的元素赋值为特殊值 null
如果长度小于原始数组的长度, 则只拷贝前面的数据元素