Java基础学习1-声明和初始化与修饰符

Made by Mike_Zhang

Java主题:

本文将记录Java基础学习的两大内容 - 声明 (Declarations)初始化 (Initialization)修饰符 (Modifiers)


先上代码:

Book.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package ultrafsih; // package named "ultrafish"

public class Book{
public String name; // public field
public int page; // public field
public boolean safe = false; // public field
public int bookAmount; // public field
private int id = 000000; // private field
protected int subBookId = 000000; // protected field
public static int totalBookUnm; // static field

Book(){
this("NoBookName"); // "this" keyword used to Calling constructors from constructors
}
Book(String initName){
this(1);
name = initName;
}
Book(int initBookAmount){
bookAmount = initBookAmount;
System.out.println("成功创建一个Book类对象,请修改书名!");
}
public Book addAmount(){
bookAmount++;
return this; // "this" keyword used to refer to the current abject
}
public void setName(String name){
this.name = name; // "this" keyword used to solve the ambiguity
}
public void seal(){
System.out.println(Sealer.getSealed(this));
// "this" keyword used to passing the current object to another method "Sealer.getSealed"
}
static void totalBookUnmAdd(){ // static method
totalBookUnm++;
}
public String getName(){
return name;
}
private void setId(int idNum){
id = idNum;
System.out.println("id set, is"+id);
}
public static void main(String[] args) {
Book myBook = new Book();
myBook.setId(000001);
System.out.println(myBook.name);
myBook.setName("MyFirstBook");
System.out.println(myBook.getName());
System.out.println(Book.totalBookUnm);
myBook.addAmount().addAmount().addAmount();
myBook.seal();
}
}
// foreign class and method
class Sealer{
static String getSealed( Book book){
book.safe = true;
return ("Sealed!");
}
}

class textBook extends Book{
textBook(){
textBook myTextBook = new textBook();
myTextBook.subBookId++;
myTextBook.bookAmount++;
}
}


Tool.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package ultrafsih;

public class Tool {
public static void main(String[] args) {
Book myBook = new Book("My Book Name");
System.out.println(myBook.name); //
System.out.println(myBook.page); //
//System.out.println(myBook.id); // Error
System.out.println(myBook.subBookId); //
System.out.println(Book.totalBookUnm); //
}
}


1. 声明 (Declarations)和初始化 (Initialization)

1.1 属性声明与初始化

之前文章的章节中有大致介绍了类的属性。
属性又称成员变量,有不同的数据类型:

数据类型名称 描述 内存大小 取值范围 默认初始值
boolean 布尔类型 1b true false false
char 字符类型 16b(2B) 0x0000~0xffff (Unicode) \u0000
byte 整数类型 8b(1B) -128~127(2^8) 0
short 整数类型 16b(2B) -32768~32767(2^16) 0
int 整数类型 32b(4B) -2147483648~2147483647(2^32) 0
long 整数类型 64b(8B) -9223372036854775808~9223372036854775807(2^64) 0L
float 单精度浮点类型 32b(4B) 1.4E-45~3.4028235E+38 0.0F
double 双精度浮点类型 64b(8B) 4.9E-324~1.7976931348623157E+308 0.0D
1
2
3
4
5
6
7
8
boolean safe = false;
char word = "A";
byte page = 1;
short pageNum = 10;
int bookNum = 2;
long loogNum = 10000L; //followed by an "L" or "l"
float floatNum = 1.3333F; //followed by an "F" or "f"
double doubleNum = 1.3333e30D; //followed by a "D" or "d"

1.2 方法声明与初始化

参考之前的文章章节

1.3 Initialization type

  1. static field initializer
  2. constructor
  3. instance initializer block
  4. instance vairable initializer
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class Hero{
    static int x = 1; // static field initializer
    String name = ""; // instance vairable initializer
    int health = 1; // instance vairable initializer

    { //instance initializer block
    health = 100;
    }

    Hero(String a, int h){ // constructor
    name = a;
    health = h;
    }
    }

1.4 Initialization order

  1. static field initializer in textual order
  2. instance initializer block and instance vairable initializer in textual order
  3. constructor

1.5 this 关键字

看以下案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Book{
// ...
private int id = 000000;
// ...

// 声明一个方法
private void setId(int idNum){
id = idNum;
System.out.println("id set, is"+id);
}

// 调用此方法
public static void main(String[] args) {
Book myBook = new Book();
myBook.setId(000001);
// ...
}
}

思考:
setId(int idNum)只有一个参数,可是在对象调用的时候只把参数值000001传递给了setId(int idNum)方法,并没有告知方法所对应的具体对象 (myBook)。

实际上,Java在编译此代码时,会编译成以下代码:

1
2
private void setId(Book this, int idNum){/*...*/} // 声明一个方法
myBook.setId(myBook, 000001); // 调用此方法

解释:
编译后,会在自动添加一个参数this,通过此参数把目前操作的对象传递到相应的方法中去。


this 关键字可以用在非静态方法中,使其指向正在调用此方法的对象。

通常用在这4种场景中:

1.当语句出现重名导致语义不清(ambiguity)时,使用 this 使其指向正在调用的对象,例如:

看一个案例:

1
2
3
public void setName(String name){
name = name;
}

setName() 方法是用来设定 name 属性的值,使其被赋值成方法中的String参数。
可是第二行的语句 name = name; 是有问题的。对象的属性名和方法的参数重名了,造成了ambiguity(模糊不清)。
这时就需要 this 关键字了,使第一个 name 清楚的代表对象的属性名。修改如下:

1
2
3
public void setName(String name){
this.name = name; // "this" keyword used to solve the ambiguity
}

2.用于return中,返回当前正在调用的对象,可以实现类似于递归的功能,例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public Book addAmount(){
bookAmount++;
return this; // "this" keyword used to refer to the current abject
}

public static void main(String[] args) {
Book myBook = new Book();
myBook.setId(000001);
System.out.println(myBook.name);
myBook.setName("MyFirstBook");
System.out.println(myBook.getName());
System.out.println(Book.totalBookUnm);
//addAmount()的返回值即为当前调用的对象,因此可以反复调用自身,功能类似于自加
myBook.addAmount().addAmount().addAmount();
//*****************************************
myBook.seal();
}

3.当一个方法内部需要访问到外部类的其他方法时,可以使用 this 传递现在指向的对象,例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Book{
/*
...
*/
public void seal(){
System.out.println(Sealer.getSealed(this));
// "this" keyword used to passing the current object to another method "Sealer.getSealed()"
}

public static void main(String[] args) {
Book myBook = new Book();
myBook.setId(000001);
System.out.println(myBook.name);
myBook.setName("MyFirstBook");
System.out.println(myBook.getName());
System.out.println(Book.totalBookUnm);
myBook.addAmount().addAmount().addAmount();
myBook.seal(); //调用方法
}
}

// foreign class and method
class Sealer{
static String getSealed( Book book){
book.safe = true;
return ("Sealed!");
}
}


4.this 关键字可以在构造函数中调用另一个构造函数,例子如下:

注:当一个类有多个构造函数时,即包含了无参构造方法 Book() 和有参构造方法 Book(String initName) ,会根据new 时调用的构造函数来选择。即:new Book()调用Book(), new Book("MyBook")调用Book(String initName), new Book(100)调用Book(int initBookAmount),参数的数据类型需要一一对应。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Book(){
this("NoBookName"); // mian() 方法调用的是 Book() 无参构造方法
// this("NoBookName"); 相当于 Book("NoBookName");,因此调用 Book(String initName) 有参构造方法
}
Book(String initName){ // 被this("NoBookName"); 调用
this(1); // 相当于 Book(1);,因此调用 Book(int initBookAmount) 有参构造方法
name = initName;
}
Book(int initBookAmount){ // 被 this(1); 调用
bookAmount = initBookAmount;
System.out.println("成功创建一个Book类对象,请修改书名!");
}

public static void main(String[] args) {
Book myBook = new Book(); //调用无参构造方法 Book()
myBook.setId(000001);
System.out.println(myBook.name);
myBook.setName("MyFirstBook");
System.out.println(myBook.getName());
System.out.println(Book.totalBookUnm);
myBook.addAmount().addAmount().addAmount();
myBook.seal();
}

注意:

当一个构造方法有两个参数时,如:Book(String initName,int initBookAmount), 使用this关键字只能传递一个参数,即this("NoBookName");this(1);, 结合体this("NoBookName",1);是不合法的。


2. 修饰符 (Modifiers)

2.1 static 修饰符

通常来说,当一个类创建完成后,我们就完成了这个类静态部分和动态部分的描述。但是只有当我们使用new关键字创建后才会真正得到一个此类的对象,并且储存这个对象的属性以及激活这个对象的方法。

但是如果

  1. 用户只想把这一类的某一个属性或者方法储存在同一个内存中,并且想统一管理,不管此类创建了多少对象;
  2. 再或者 想在创建此类的的对象前就能访问类的静态和动态部分,不关联任何一个此类的对象

举个实例:

创建一个名为纸质书的类, 并创建一个名为材质的属性。那通常来说纸质书类的材质属性值就为,适用于所有的纸质书对象,不需要为每一位对象单独添加一个材质属性,只需要统一管理。并且不需要创建任何对象,就可以访问或者修改材质属性值。

那我们可以说这一类属性或方法是统一的或者是静态的(static),那在Java中这一类的就用static修饰符来修饰其静态的特征。

举例:

1
public static int totalBookUnm; // static field

上述例子中,在Book类中创建了一个名为totalBookUnm的静态属性。并在下面对其进行访问。

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
Book myBook = new Book();
myBook.setId(000001);
System.out.println(myBook.name);
myBook.setName("MyFirstBook");
System.out.println(myBook.getName());
System.out.println(Book.totalBookUnm); //访问静态属性,直接使用类名Book,无须使用对象名myBook
myBook.seal();
}

注意:

  1. 类的静态属性和方法不会联系到类所创建的任何一个特定的对象;
  2. 无须创建一个此类的对象即可访问到此类的静态属性和方法;
  3. 对于非静态的属性和方法,必须创建一个此类的对象才能访问。

静态属性和方法最大的用处就是,它允许我们在不创建然后此类的对象的条件下都可以访问其属性和方法。

主函数(主方法)main() 就是一个静态方法,无须创建对象即可访问:

1
public static void main(String[] args) {/*...*/}

static 看起来有如此高的访问权限,当它遇到访问权限修饰符 public, protectedprivate 的时候会发生什么呢,下文会提到。


2.2 访问权限修饰符 (Access Control Modifiers)

Java是一门面向对象的编程语言 (Object Oriented Programming),封装性 (Encapsulation)是其一大特征, 旨在把过程抽象并隐藏起来,并只允许客户访问必要的要素,这样可以保护项目的安全,不会担心外部客户影响内部功能,也可以避免内部功能的改变影响到客户对项目的使用。因此访问控制 (Access Control) 就起到了看门人的作用,设置了三道拥有不同权限的门,即public, protectedprivate,称为访问权限修饰符 (Access Control Modifiers)。

2.2.1 public

public 的属性和方法是对所有人开放的,包括 本类,子类,同包内的类,不同包内的类。例如:

Book.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Book{
public String name; // public field
public int page; // public field
public boolean safe = false; // public field
public int bookAmount; // public field

public Book addAmount(){
bookAmount++; // 类内方法访问 public 属性
return this;
}
public void setName(String name){ // public method
this.name = name;
}
public static void main(String[] args) {
Book myBook = new Book();
myBook.setId(000001);
System.out.println(myBook.name); // 访问 public 属性
myBook.setName("MyFirstBook"); // 访问 public 方法
System.out.println(myBook.getName()); // 访问 public 方法
}
}
// foreign class and method
class Sealer{
static String getSealed( Book book){
book.safe = true; //其他类访问 public 属性
return ("Sealed!");
}
}
// 子类
class textBook extends Book{
textBook(){
textBook myTextBook = new textBook();
myTextBook.subBookId++;
myTextBook.bookAmount++; //子类访问 public 属性
}
}

Tool.java

1
2
3
4
5
6
7
8
package ultrafsih;
public class Tool {
public static void main(String[] args) {
Book myBook = new Book("My Book Name");
System.out.println(myBook.name); // 同包的类访问 public 属性
System.out.println(myBook.page); // 同包的类访问 public 属性
}
}

2.2.2 protected

protected的属性和方法相比于public减少了外部类(不同包的类)的访问权限,强调了继承类的访问,权限包括 本类,子类,同包内的类,以及不同包中的子类*。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Book{
protected int subBookId = 000000; // protected field
public static void main(String[] args) {
Book myBook = new Book();
myBook.setId(000001);
System.out.println(myBook.name);
myBook.setName("MyFirstBook");
System.out.println(myBook.getName());
System.out.println(Book.totalBookUnm);
myBook.addAmount().addAmount().addAmount();
myBook.seal();
}
}
class textBook extends Book{
textBook(){
textBook myTextBook = new textBook();
myTextBook.subBookId++; //子类访问 protected 属性
myTextBook.bookAmount++;
}
}

*Notice:
In different package, superclass’s protected number can be accessed by it’s subclass instance, but NOT the superclass’s instance in the subclass.

1
2
3
4
package p;
public class A {
protected int x;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package q;
import p.A;
public class B extends A {
void f(A a) {
a.x = 1; // Illegal access from instance of the supclass
}
void f() {
x = 1; // OK, x is inherited from the superclass, accessed through the subclass
}
void f() {
super.x = 1 // OK, super is a special case, actually is inherited
}
}

Tool.java

1
2
3
4
5
6
7
8
package ultrafsih;

public class Tool {
public static void main(String[] args) {
Book myBook = new Book("My Book Name");
System.out.println(myBook.subBookId); // 同包的类访问 protected 属性
}
}

2.2.3 default-access

若不加访问权限修饰符,则为默认访问权限。其类似于protected的访问范围,但只能在同一个包内访问,不能访问不同包内的子类。权限包括 本类,子类,同包内的类,但不包括 不同包中的子类


2.2.4 private

private的属性和方法限制最多,只有其所在的类可以访问。其子类,或者同一包内的类都不能访问。例如:

Book.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Book{
private int id = 000000; // private field

private void setId(int idNum){ // private method
id = idNum;
System.out.println("id set, is"+id);
}
public static void main(String[] args) {
Book myBook = new Book();
myBook.setId(000001); // No error, in a same class with field "id" and method "setId"
}
}
// foreign class and method
class Sealer{
static String getSealed( Book book){
book.safe = true;
return ("Sealed!");
book.setId(000002); // Error, access setId() in a foreign class
}
}
class textBook extends Book{
textBook(){
textBook myTextBook = new textBook();
myTextBook.setId(000003); // Error, access setId() in a child class
}
}

Tool.java

1
2
3
4
5
6
7
8
package ultrafsih;

public class Tool {
public static void main(String[] args) {
Book myBook = new Book("My Book Name");
System.out.println(myBook.id); // Error, access setId() in another class in a same package
}
}

private成员甚至限制了开发者对于项目的访问权限,但是这也减小了在修改此成员时对处于同一包内其他类的影响。


2.2.4 staticpublic, protectedprivate

上文提过,static看起来有如此高的访问权限,到那时访问权限修饰符(access specifiers)的等级还是高于static,当遇到private static时, 修饰的对象还是只有其所在的类可以访问。


2.3 final 修饰符

final 修饰符是用来修饰某一成员是一个常量,是不能被修改的。final 修饰符可以用来修饰类的属性,参数,方法以及一整个类。例如:

1
public final boolean safe = false; // safe 属性被final修饰,其值只能被对象读取,无法被修改

2.3.1 final 属性

属性(field)常量指的是类的某一属性值为常量,分为编译时常量( compile-time constant)和空白常量(blank finals)

2.3.1.1 编译时常量

编译时常量( compile-time constant)需要在声明时被初始化,即给定属性值,例如:

1
public final boolean safe = false; // safe 属性被final修饰,为编译时常量,需要被赋值

finalstatic 修饰符同时修饰一个属性时,此属性名通常由大写字母组成,并且词间用下划线(_)分割,如下:

1
public static final int TOTAL_BOOK_NUM = 100; 

注:当 static final 修饰一个属性时,此属性值不会随着对象的创建而改变,这也是 static修饰符自带的特性。而当仅仅一个 final 修饰属性时,其属性值可能会随着对象的创建而修改,但是在对象创建后,此属性值不能被修改,
例子如下:

1
2
3
4
public class finalTest{
public static final int INT_ONE = rand.nextInt(10);
public final int int_two = rand.nextInt(10);
}

两个属性INT_ONEint_two都被赋值成随机数。

1
2
finalTest t1 = new finalTest();
finalTest t2 = new finalTest();

创建两个对象t1和t2,假设创建后t1两个属性为:

1
2
t1.INT_ONE = 5;
t1.int_two = 2;

则:

1
2
t2.INT_ONE = 5; // 静态的、编译时常量,不会随着不同对象的创建而变化,创建后属性值也不能被覆盖
t1.int_two = 3; // 编译时常量,会随着不同对象的创建而变化,但是创建后属性值不能被覆盖

同时,这个例子也表明了,编译时常量( compile-time constant)并不代表在表达式内就需要明确属性值,INT_ONEint_two 都是在运行程序时被随机数函数赋值的。

Notice:
final protects only the variable itself.
If the variable is a reference, final does not protect the object that reference points to.

1
2
3
final Object obj = new Object();
obj = new Object(); // Error
obj.setName("obj2"); // OK

protect obj instance itself;
not including the object it points to(e.g. name)


2.3.1.2 空白常量

空白常量 (blank final) 不需要需要在声明时被初始化,即不需要给定属性值,例如:

1
public final boolean safe;

但是空白常量在使用前必须被赋值,通常会在构造方法中进行赋值。

总之,不管是 编译时常量( compile-time constant) 还是 空白常量 (blank final) 都需要在使用前被赋值,即在声明中或者构造方法中被赋值。


2.3.2 final 参数

final 参数可以修饰某一方法的形式参数为常量,在这个方法内,不能对此形式参数所指向的参数进行修改,只能读取此参数值,例如:

1
2
3
4
5
6
7
class Sealer{
static String getSealed(final Book book){
book = new Book(); // Error, illegal to rewrite "book"
book.safe = true;
return ("Sealed!");
}
}

或:

1
2
3
4
5
public void setId(final int idNum){
idNum++; // Error, illegal to rewrite "idNum"
id = idNum + 1; // OK, can only read "idNum"
System.out.println("id set, is"+id);
}


2.3.3 final 方法

final 方法用来修饰某一类的方法为常量,如下:

1
2
3
public final String getName(){
return name;
}

final 方法主要有两个目的:

  1. 保护一个类的某一方法被重写,尤其是保护此方法被此类的继承类(子类)重写,例如:
1
2
3
4
5
6
7
8
9
10
11
// getName()为父类Book的一个final方法
public final String getName(){
return name;
}

//textBook是继承Book的子类
class textBook extends Book{
public final String getName(){ // 重写父类的方法
return ("This textBook's name is, " + name); // Error, getName()为父类Book的一个final方法,不能被重写
}
}

  1. 提高代码的运行效率。
    编译时,编译器会优先运行被final修饰的方法,因此程序员可以根据需求,告知编译器需要优先运行那一部分的方法。然而在Java SE 5/6中,编译器以及JVM会处理程序的编译优先级,自动提高运行效率。

总之,目前只有当程序员需要保护某些方法不被重写才会使用到 final


注意:

finalprivate同时修饰一个方法:
事实上任何 private方法都是 final,因为不能从一个类的外部访问private方法,因此当然不能对其进行修改,成为 final。所以给一个 private方法加上 final修饰符并没有什么意义。

但是当在重写一个 final private方法时,情况会变得不一样,举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// getName()和getBookName()为父类Book的两个方法
private final String getName(){
return name;
}
private String getBookName(){
return ("The name is: " + name);
}

//textBook是继承Book的子类
class textBook extends Book{
private final String getName(){ // 重写父类Book的方法(private final)
return ("This textBook's name is, " + name);
}
private String getBookName(){ // 重写父类Book的方法(private)
return ("This textBook's name is, " + name);
}
}

//workBook是继承textBook的子类
class workBook extends textBook{
public final String getName(){ // 重写父类textBook的方法(public final)
return ("This workBook's name is, " + name);
}
public String getBookName(){ // 重写父类textBook的方法(public)
return ("This workBook's name is, " + name);
}
}
// 在main()中运行以下代码:
// 下面的代码正常运行,无报错
textBook myTextBook = new textBook("newTextBook");
myTextBook.getName();
myTextBook.getBookName();
// **********************
// 下面的代码运行失败,报错
workBook myTextBook2 = myTextBook; // upcating
myTextBook2.getName();
myTextBook2.getBookName();

解释:

子类不能重写父类中的 final方法是因为每当子类运行重写父类的方法时,都会回溯到父类,与父类中的被继承方法进行连接,但是因为final而被阻止。
但是当子类“重写父类private方法”时,子类并不能访问到父类的private方法,这也正是private修饰的特性。因此这个看似“重写父类private方法”方法,并没有重写父类的方法,只是在子类中创建了一个属于子类的新方法,只不过与父类方法刚好重名了,所以并无关联。
而例子中不能运行的代码,是因为没有重写父类方法而导致不能使用多态(Polymorphism)

3.3.4 final

final 类修饰的是整个类,修改整个类或者对此类进行继承都是不允许的。final 类可以保障一个类的安全,适用于一个不用被修改的类,例如:

1
2
3
4
5
6
final class Sealer{
static String getSealed( Book book){
book.safe = true;
return ("Sealed!");
}
}

当一个类被 final 修饰后,其属性值还是可以被改变,也可以选择其属性是否被 final进行修饰。
但是其方法就同样为final,不能被修改,这样才保证了 final类不会被继承,其方法不会被重写。final类中的方法前可选加final修饰符,但是不会有任何其他意义。


2.4 package 语句

在Java中,每个独立的public类都被安排在分开的文件夹中,每个文件夹中可能还包括其他的非public的类。为了更好的管理这些有关联的类,可以应用到packagepackage包含了一组class,并且被管理在统一的namespace(命名空间)下。
这些有关系的类必须放在一个名packageName的文件夹中,并且每个类的源文件必须把以下代码写在开头:

1
package packageName;

例如,定义一个名为trianglepackage,并包含RightTriangleIsoscelesTriangle两个类,那必须在这两个类文件开头写出 package 语句,否则这两个文件就被放在 default package 中。如果需要引用package中的类,就需要使用fully qualified name,例如:

triangle.RightTriangle :引用RightTriangle
triangle.IsoscelesTriangle :引用IsoscelesTriangle

同时,在 package 文件夹中也可以定义子文件夹,并通过fully qualified name去引用,以Scanner类举例:

Scanner类位于java.util这一子文件夹中,可以用以下语句引用到Scanner类:
java.util.Scanner


如果要引用Scanner类创建对象,则可以使用它的fully qualified name:

1
java.util.Scanner input = new java.util.Scanner(System.in);

但是每次都使用fully qualified name会十分麻烦,那就可以使用import语句导入某个类或者一整个package,如下:

import packageName.className;或者
import packageName.*;

Scanner类为例:

1
2
import java.util.Scanner; // 导入一个类
import java.util.*; // 导入一整个package

则在创建对象时就可以使用类名:

1
2
3
import java.util.Scanner
// import java.util.*
Scanner input = new Scanner(System.in);

注意:如果从两个不同的package中import两个相同名字的类,或者import的类与现有现有的类重名的话,单单使用一个unqualified name是不合法的,如:

1
2
3
4
5
import abox.tool;
import bbox.tool;
tool myTool = new tool(); // Error!
abox.tool myToola = new abox.tool(); // OK
bbox.tool myToolb = new bbox.tool(); // OK

例如:

此语句同时写在Book.java和Tool.java两个文件中,因此两个文件可以互相访问对方的class。

Tool.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package ultrafsih;

public class Tool {
public static void main(String[] args) {
Book myBook = new Book("My Book Name");
System.out.println(myBook.name); //访问Book类的属性
System.out.println(myBook.page); //访问Book类的属性
//System.out.println(myBook.id); // Error
System.out.println(myBook.subBookId); //
System.out.println(Book.totalBookUnm); //
}
}


Tool类因为包含在ultrafish package中,因此它可以直接访问同样在package中Book类属性以及方法。因此使用package可以很方便的管理需要访问不同Java文件的Java开发工程。

注意:

  1. package语句必须写在Java文件除注释以外的第一行;
  2. package语句中的包名一般使用小写字母。
  3. 建议把包文件放在同一个子目录下,可以解决 重名 以及 寻找class不易 的问题

参考

B. Eckel, Thinking in java. Upper Saddle River, N.Y. Prentice Hall, 2014.
M. Goodrich, R. Tamassia, and A. O’reilly, Data Structures and Algorithms in Java, 6th Edition. John Wiley & Sons, 2014.


写在最后

Java相关的基础知识十分重要,会继续学习,继续更新.
最后,希望大家一起交流,分享,指出问题,谢谢!


原创文章,转载请标明出处
Made by Mike_Zhang




感谢你的支持

Java基础学习1-声明和初始化与修饰符
https://ultrafish.io/post/Java-learning-1/
Author
Mike_Zhang
Posted on
September 2, 2021
Licensed under