Java Learning_Note #2
Java Learning Note_2
1.基础语法
组成:
- 大小写敏感
- 类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母应该大写
- 所有的方法名都应该以小写字母开头
- 源文件名必须和public 类名相同
- 主方法入口:所有的 Java 程序由 public static void main(String[] args) 方法开始执行。
1.1 标识符
- 所有的标识符(类名、方法名、变量名)都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始
- 合法标识符举例:age、$salary、_value、__1_value
1.2 修饰符
1.2.1 访问控制修饰符 : default, public , protected, private
- default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法(接口里的变量都隐式声明为 public static final,而接口里的方法默认情况下访问权限为 public)
- private : 在同一类内可见。使用对象:变量、方法 注意:不能修饰类(外部类)
- public : 对所有类可见。使用对象:类、接口、变量、方法
- protected : 对同一包内的类和所有子类可见。使用对象:变量、方法 注意:不能修饰类(外部类)
- 子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;
- 子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。
1.2.2 非访问控制修饰符 : final, abstract, static, synchronized
-
final:用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
- final变量:
- 变量一旦赋值后,不能被重新赋值。被 final 修饰的实例变量必须显式指定初始值
- final 修饰符通常和 static 修饰符一起使用来创建类常量
- final 方法:
- 可以被子类继承,但是不能被子类重写
- 防止该方法的内容被修改
- final 类:
- 不能被继承,没有类能够继承 final 类的任何特性
- final变量:
-
abstract:用来创建抽象类和抽象方法。
-
抽象类:
- 抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。
- 一个类不能同时被 abstract 和 final 修饰。
- 如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。
- 抽象类可以包含抽象方法和非抽象方法。
-
抽象方法:
- 一种没有任何实现的方法,该方法的具体实现由子类提供
- 抽象方法不能被声明成 final 和 static
- 子类必须实现父类的所有抽象方法,除非该子类也是抽象类
- 一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法
- 声明以分号结尾,例如:public abstract sample();
-
举例:
public abstract class SuperClass{ abstract void m(); //抽象方法 } class SubClass extends SuperClass{ //实现抽象方法 void m(){ ......... } }
-
-
static:用来修饰类方法和类变量。
-
静态变量/类变量:
无论一个类实例化多少对象,它的静态变量只有一份拷贝。 局部变量不能被声明为 static 变量
-
静态方法:
static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据
-
-
synchronized 和 volatile:主要用于线程的编程.
-
synchronized 修饰符:
声明的方法同一时间只能被一个线程访问
-
volatile 修饰符:
- 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。
- 当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值
-
-
transient 修饰符:序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量
1.3 变量类型
1.3.1 局部变量
- 在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁
- 访问修饰符不能用于局部变量
- 在栈上分配
- 没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。(没有初始化,在编译时会出错)
1.3.2 成员变量/实例变量(非静态变量)
- 定义在类中,方法体之外的变量,在创建对象的时候实例化
- 实例变量在对象创建的时候创建,在对象被销毁的时候销毁
- 实例变量可以声明在使用前或者使用后
- 访问修饰符可以修饰实例变量。一般情况下应该把实例变量设为私有。通过使用访问修饰符public可以使实例变量对子类可见
- 实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null
- 实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:ObejectReference.VariableName
1.3.3 类变量(静态变量)
- 也称为静态变量,在类中以 static 关键字声明,但必须在方法之外
- 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝
- 除了被声明为常量外很少使用,静态变量是指声明为 public/private,final 和 static 类型的变量。静态变量初始化后不可改变
- 储存在静态存储区
- 在第一次被访问时创建,在程序结束时销毁
- 默认值同成员变量
- 类变量被声明为 public static final 类型时,类变量名称一般建议使用大写字母
1.4 关键字
1.5 注释、空行和面向对象
- 注释:同C和C++(//;/**/)
- 空行:编译器忽略
- 面向对象:类似C++,支持以下基本概念
- 多态
- 继承
- 封装
- 抽象
- 类
- 对象
- 实例
- 方法
- 重载
1.6 接口
- 接口可理解为对象间相互通信的协议。
- 接口只定义派生要用到的方法,但是方法的具体实现完全取决于派生类。
1.7 运算符
1.7.1 算术运算符
-
基本算术运算符(加减乘除、取余)
-
自增自减运算符
- 前缀自增自减法(++a,--a): 先进行自增或者自减运算,再进行表达式运算
- 后缀自增自减法(a++,a--): 先进行表达式运算,再进行自增或者自减运算
1.7.2 关系运算符
运算符 | 描述 | 例子 |
---|---|---|
== | 检查如果两个操作数的值是否相等,如果相等则条件为真。 | (A == B)为假。 |
!= | 检查如果两个操作数的值是否相等,如果值不相等则条件为真。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是那么条件为真。 | (A> B)为假。 |
< | 检查左操作数的值是否小于右操作数的值,如果是那么条件为真。 | (A <B)为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。 | (A> = B)为假。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。 | (A <= B)为真。 |
1.7.3 位运算符
操作符 | 描述 | 例子 |
---|---|---|
& | 如果相对应位都是1,则结果为1,否则为0 | (A&B),得到12,即0000 1100 |
| | 如果相对应位都是 0,则结果为 0,否则为 1 | (A | B)得到61,即 0011 1101 |
^ | 如果相对应位值相同,则结果为0,否则为1 | (A ^ B)得到49,即 0011 0001 |
〜 | 按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 | (〜A)得到-61,即1100 0011 |
<< | 按位左移运算符。左操作数按位左移右操作数指定的位数。 | A << 2得到240,即 1111 0000 |
>> | 按位右移运算符。左操作数按位右移右操作数指定的位数。 | A >> 2得到15即 1111 |
>>> | 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 | A>>>2得到15即0000 1111 |
1.7.4 逻辑运算符
操作符 | 描述 | 例子 |
---|---|---|
&& | 称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。 | (A && B)为假。 |
| | | 称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。 | (A | | B)为真。 |
! | 称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。 | !(A && B)为真。 |
-
短路逻辑运算符
当使用与逻辑运算符时,在两个操作数都为true时,结果才为true,但是当得到第一个操作为false时,其结果就必定是false,这时候就不会再判断第二个操作了。
1.7.5 赋值运算符
操作符 | 描述 | 例子 |
---|---|---|
= | 简单的赋值运算符,将右操作数的值赋给左侧操作数 | C = A + B将把A + B得到的值赋给C |
+ = | 加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数 | C + = A等价于C = C + A |
- = | 减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数 | C - = A等价于C = C - A |
* = | 乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数 | C * = A等价于C = C * A |
/ = | 除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数 | C / = A,C 与 A 同类型时等价于 C = C / A |
(%)= | 取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数 | C%= A等价于C = C%A |
<< = | 左移位赋值运算符 | C << = 2等价于C = C << 2 |
>> = | 右移位赋值运算符 | C >> = 2等价于C = C >> 2 |
&= | 按位与赋值运算符 | C&= 2等价于C = C&2 |
^ = | 按位异或赋值操作符 | C ^ = 2等价于C = C ^ 2 |
| = | 按位或赋值操作符 | C | = 2等价于C = C | 2 |
1.7.6 条件运算符/三元运算符(?:)
举例:
// 如果 a 等于 1 成立,则设置 b 为 20,否则为 30
b = (a == 1) ? 20 : 30;
1.7.7 instanceof 运算符
-
用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)
-
如果运算符左侧变量所指的对象,是操作符右侧类或接口(class/interface)的一个对象,那么结果为真
String name = "James"; boolean result = name instanceof String; // 由于 name 是 String 类型,所以返回真
-
如果被比较的对象兼容于右侧类型,该运算符仍然返回true
class Vehicle {} public class Car extends Vehicle { public static void main(String[] args){ Vehicle a = new Car(); boolean result = a instanceof Car; System.out.println( result); } } /**输出结果 true **/
1.7.8 Java运算符优先级
下表中具有最高优先级的运算符在的表的最上面,最低优先级的在表的底部
类别 | 操作符 | 关联性 |
---|---|---|
后缀 | () [] . (点操作符) | 左到右 |
一元 | expr++ expr-- | 从左到右 |
一元 | ++expr --expr + - ~ ! | 从右到左 |
乘性 | * /% | 左到右 |
加性 | + - | 左到右 |
移位 | >> >>> << | 左到右 |
关系 | > >= < <= | 左到右 |
相等 | == != | 左到右 |
按位与 | & | 左到右 |
按位异或 | ^ | 左到右 |
按位或 | | | 左到右 |
逻辑与 | && | 左到右 |
逻辑或 | | | | 左到右 |
条件 | ?: | 从右到左 |
赋值 | = + = - = * = / =%= >> = << =&= ^ = | = | 从右到左 |
逗号 | , | 左到右 |
1.8 循环结构
Java中有三种主要的循环结构:
- while 循环
- do…while 循环
- for 循环
- 增强for循环
以及两种用于循环的关键字:
- break关键字(break 跳出最里层的循环,并且继续执行该循环下面的语句)
- continue关键字(让程序立刻跳转到下一次循环的迭代)
- 在 for 循环中,continue 语句使程序立即跳转到更新语句
- 在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句
1.8.1 while循环
while( 布尔表达式 ) {
//循环内容
}
1.8.2 do...while循环
即使不满足条件,也至少执行一次
do {
//代码语句
}while(布尔表达式);
1.8.3 for循环
for(初始化; 布尔表达式; 更新) {
//代码语句
}
1.8.4 增强for循环
for(声明语句 : 表达式)
{
//代码句子
}
public class Test {
public static void main(String[] args) {
int [] numbers = {10, 20, 30, 40, 50};
for(int x : numbers ) {
if( x == 30 ) {
continue;
}
System.out.print( x );
System.out.print("\n");
}
}
}
1.9 条件语句
1.9.1 if...else if...else语句
- 可嵌套
if(布尔表达式 1){
//如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
//如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
//如果布尔表达式 3的值为true执行代码
}else {
//如果以上布尔表达式都不为true执行代码
}
1.9.2 switch case语句
- 判断一个变量与一系列值中某个值是否相等,每个值称为一个分支
- switch 语句中的变量类型可以是: byte、short、int 或者 char、String
- case 语句中的值的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量
- 当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句
- 如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句
- default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句
switch(expression){
case value :
//语句
break; //可选
case value :
//语句
break; //可选
//你可以有任意数量的case语句
default : //可选
//语句
}
- 举例:如果 case 语句块中没有 break 语句时,匹配成功后,从当前 case 开始,后续所有 case 的值都会输出
public class Test {
public static void main(String args[]){
int i = 1;
switch(i){
case 0:
System.out.println("0");
case 1:
System.out.println("1");
case 2:
System.out.println("2");
case 3:
System.out.println("3"); break;
default:
System.out.println("default");
}
}
}
/**
以上代码编译运行结果如下:
1
2
3
**/
1.10 数组
数组是引用传递 ,将引用 赋值为 null 只是将引用数组不指向任何对象 ,并不会对原先指向的对象数据进行修改
1.10.1 声明数组变量
首先必须声明数组变量,才能在程序中使用数组:
dataType[] arrayRefVar; // 首选的方法
或
dataType arrayRefVar[]; // 效果相同,但不是首选方法
1.10.2 创建数组
用new操作符来创建:
arrayRefVar = new dataType[arraySize];
- 使用 dataType[arraySize] 创建了一个数组
- 把新创建的数组的引用赋值给变量 arrayRefVar
数组变量的声明,和创建数组可以用一条语句完成:
dataType[] arrayRefVar = new dataType[arraySize];
或
dataType[] arrayRefVar = {value0, value1, ..., valuek};
-
举例:
- 首先声明了一个数组变量 myList,接着创建了一个包含 10 个 double 类型元素的数组,并且把它的引用赋值给 myList 变量
public class TestArray { public static void main(String[] args) { // 数组大小 int size = 10; // 定义数组 double[] myList = new double[size]; myList[0] = 5.6; myList[1] = 4.5; myList[2] = 3.3; myList[3] = 13.2; myList[4] = 4.0; myList[5] = 34.33; myList[6] = 34.0; myList[7] = 45.45; myList[8] = 99.993; myList[9] = 11123; // 计算所有元素的总和 double total = 0; for (int i = 0; i < size; i++) { total += myList[i]; } System.out.println("总和为: " + total); } }
1.10.3 处理数组
数组的元素类型和数组的大小都是确定的,所以当处理数组元素时候,我们通常使用基本循环或者 For-Each 循环
-
基本循环:
public class TestArray { public static void main(String[] args) { double[] myList = {1.9, 2.9, 3.4, 3.5}; // 打印所有数组元素 for (int i = 0; i < myList.length; i++) { System.out.println(myList[i] + " "); } // 计算所有元素的总和 double total = 0; for (int i = 0; i < myList.length; i++) { total += myList[i]; } System.out.println("Total is " + total); // 查找最大元素 double max = myList[0]; for (int i = 1; i < myList.length; i++) { if (myList[i] > max) max = myList[i]; } System.out.println("Max is " + max); } }
-
For-Each循环:(能在不使用下标的情况下遍历数组)
public class TestArray { public static void main(String[] args) { double[] myList = {1.9, 2.9, 3.4, 3.5}; // 打印所有数组元素 for (double element: myList) { System.out.println(element); } } }
1.10.4 作为函数的参数/返回值
- 作为函数的参数:
public static void printArray(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
printArray(new int[]{3, 1, 2, 6, 4, 2}); //调用
- 作为函数的返回值:
public static int[] reverse(int[] list) {
int[] result = new int[list.length];
for (int i = 0, j = result.length - 1; i < list.length; i++, j--) {
result[j] = list[i];
}
return result;
}
list作为函数参数、result作为函数返回值
1.10.5 多维数组
-
动态初始化(二维数组为例):
-
直接为每一维分配空间,格式如下:
int[][] a = new int[2][3]; //两行三列数组
-
从最高维开始,分别为每一维分配空间:
String[][] s = new String[2][]; s[0] = new String[2]; s[1] = new String[3]; s[0][0] = new String("Good"); s[0][1] = new String("Luck"); s[1][0] = new String("to"); s[1][1] = new String("you"); s[1][2] = new String("!");
s[0]=new String[2] 和 s[1]=new String[3] 是为最高维分配引用空间,也就是为最高维限制其能保存数据的最长的长度,然后再为其每个数组元素单独分配空间
s[0][0]=new String("Good")
等操作
-
-
引用(二维数组为例):
对二维数组中的每个元素,引用方式为
arrayName[index1][index2]
,例如:num[1][0];
1.10.6 Arrays类
-
使用java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的
- 给数组赋值:通过 fill 方法
- 对数组排序:通过 sort 方法,按升序
- 比较数组:通过 equals 方法比较数组中元素值是否相等
- 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作
-
具体说明:
序号 方法和说明 1 public static int binarySearch(Object[] a, Object key) 用二分查找算法在给定数组中搜索给定值的对象(Byte,Int,double等)。数组在调用前必须排序好的。如果查找值包含在数组中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。 2 public static boolean equals(long[] a, long[] a2) 如果两个指定的 long 型数组彼此相等,则返回 true。如果两个数组包含相同数量的元素,并且两个数组中的所有相应元素对都是相等的,则认为这两个数组是相等的。换句话说,如果两个数组以相同顺序包含相同的元素,则两个数组是相等的。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。 3 public static void fill(int[] a, int val) 将指定的 int 值分配给指定 int 型数组指定范围中的每个元素。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。 4 public static void sort(Object[] a) 对指定对象数组根据其元素的自然顺序进行升序排列。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。
1.11 正则表达式
- 正则表达式定义了字符串的模式、可以用来搜索、编辑或处理文本、并不仅限于某一种语言,但是在每种语言中有细微的差别
简单举例:
正则表达式 | 描述 |
---|---|
this is text | 匹配字符串 "this is text" |
this\s+is\s+text | 注意字符串中的 \s+。匹配单词 "this" 后面的 \s+ 可以匹配多个空格,之后匹配 is 字符串,再之后 \s+ 匹配多个空格然后再跟上 text 字符串。可以匹配这个实例:this is text |
^\d+(.\d+)? | ^ 定义了以什么开始 \d+ 匹配一个或多个数字 ? 设置括号内的选项是可选的 \. 匹配 "." 可以匹配的实例:"5", "1.5" 和 "2.21"。 |
具体内容:Java 正则表达式
2.Java数据类型、类型转换与文件声明
2.1 基本数据类型
Java 的两大数据类型:
- 内置数据类型
- 引用数据类型
2.1.1 内置数据类型
八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。
-
整数型:
-
byte:数据类型是8位(最小值是 -128(-2^7)、最大值是 127(2^7-1))、有符号的,以二进制补码表示的整数,默认值0,占用的空间只有 int 类型的四分之一
byte a = 100,byte b = -50
-
short:数据类型是 16 位(最小值是 -32768(-2^15)、最大值是 32767(2^15 - 1))、有符号的以二进制补码表示的整数,默认值0,占用的空间只有 int 类型的二分之一
short s = 1000,short r = -20000
-
int:数据类型是 32 位(最小值是-2,147,483,648(-2^31)、最大值是 2,147,483,647(2^31 - 1))、有符号的以二进制补码表示的整数,默认值0,一般地整型变量默认为 int 类型
int a = 100000, int b = -200000
-
long:数据类型是 64 位(最小值是 -9,223,372,036,854,775,808(-2^63)、最大值是 9,223,372,036,854,775,808(2^63 - 1))、有符号的以二进制补码表示的整数,默认值0L,这种类型主要使用在需要比较大整数的系统上
long a = 100000L,Long b = -200000L
-
-
浮点型:(不能用来表示精确的值,如货币)
-
float:数据类型是单精度、32位、符合IEEE 754标准的浮点数,默认值为0.0f,在储存大型浮点数组的时候可节省内存空间
float f1 = 234.5f
-
double:数据类型是双精度、64位、符合IEEE 754标准的浮点数,默认值为0.0d
double d1 = 7D ; double d2 = 7.; double d3 = 8.0; double d4 = 8.D; double d5 = 12.9867; //7 是一个 int 字面量,而 7D,7. 和 8.0 是 double 字面量
-
-
字符型:
- char:是一个单一的 16 位 Unicode 字符(最小值是 \u0000(十进制等效值为 0)、最大值是 \uffff(即为 65535)),可以储存任何字符,默认值为'u0000'
-
布尔型:
- boolean:表示一位的信息(只有两个取值:true 和 false),默认值为false
2.1.2 引用类型与常量
- 引用类型
- 引用类型的变量非常类似于C/C++的指针
- 对象、数组都是引用数据类型
- 所有引用类型的默认值都是null
- 一个引用变量可以用来引用任何与之兼容的类型
Site site = new Site("Runoob")
-
常量(字面量)
- 使用 final 关键字来修饰常量,声明方式和变量类似
- 通常使用大写字母表示常量
- 字面量可以赋给任何内置类型的变量
- 当使用字面量的时候,前缀 0 表示 8 进制,而前缀 0x 代表 16 进制
final double PI = 3.1415927; // byte a = 68; char a = 'A'; // int decimal = 100; int octal = 0144; int hexa = 0x64; // char a = '\u0001'; String a = "\u0001";
- 支持一些特殊的转义字符序列
符号 字符含义 \n 换行 (0x0a) \r 回车 (0x0d) \f 换页符(0x0c) \b 退格 (0x08) \0 空字符 (0x0) \s 空格 (0x20) \t 制表符 " 双引号 ' 单引号 \ 反斜杠 \ddd 八进制字符 (ddd) \uxxxx 16进制Unicode字符 (xxxx)
2.2 自动类型转换
整型、实型(常量)、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算。
必须满足如下规则:
-
不能对boolean类型进行类型转换
-
不能把对象类型转换成不相关类的对象
-
在把容量大的类型转换为容量小的类型时必须使用强制类型转换
-
转换过程中可能导致溢出或损失精度:
int i =128; byte b = (byte)i; //byte 类型是 8 位,最大值为127,所以当 int 强制转换为 byte 类型时,值 128 时候就会导致溢出
-
浮点数到整数的转换是通过舍弃小数得到,而不是四舍五入:
(int)23.7 == 23; (int)-45.89f == -45
转换低级到高级:
低 ------------------------------------> 高
byte,short,char—> int —> long—> float —> double
2.2.1 自动类型转换
必须满足转换前的数据类型的位数要低于转换后的数据类型,例如:
- short数据类型的位数为16位,就可以自动转换位数为32的int类型
- 同样float数据类型的位数为32,可以自动转换为64位的double类型
2.2.2 强制类型转换
- 条件是转换的数据类型必须是兼容的(高-》低)
- 格式:(type)value,type是要强制类型转换后的数据类型
2.2.3 隐含强制类型转换
- 整数的默认类型是 int
- 小数默认是 double 类型浮点型,在定义 float 类型时必须在数字后面跟上 F 或者 f
2.3 源文件声明规则
当在一个源文件中定义多个类,并且还有import语句和package语句时,要特别注意这些规则:
- 一个源文件中只能有一个 public 类,但可以有多个非 public 类
- 源文件的名称应该和 public 类的类名保持一致
- 如果一个类定义在某个包中,那么 package 语句应该在源文件的首行
- 如果源文件包含 import 语句,那么应该放在 package 语句和类定义之间。如果没有 package 语句,那么 import 语句应该在源文件中最前面
- import 语句和 package 语句对源文件中定义的所有类都有效
· 一则复杂 SQL 改写后有感
· 曾经风光无限的 Oracle DBA 已经落伍了吗?
· 接口被刷百万QPS,怎么防?
· C# 锁机制全景与高效实践:从 Monitor 到 .NET 9 全新 Lock
· 一个开源免费、功能丰富的 WPF 自定义控件资源库