java day6
第六章 包、接口和其他类特性
- 6.1 限定符
- 6.2 静态变量和方法
- 6.3 final类、方法和变量
-
- 6.3.1 变量
- 6.3.2 方法
- 6.3.3 类
- 6.4 抽象类和方法
- 6.5 包
-
- 6.5.1 import 声明
- 6.5.2 类名冲突
- 6.6 创建自己的包
-
- 6.6.1 选择包名
- 6.6.2 创建文件夹结构
- 6.6.3 将类加入到包中
- 6.6.4 包和类访问控制
- 6.7 接口
-
- 6.7.1 单继承存在的问题
- 6.7.2 接口和类
- 6.7.3 实现和使用接口
- 6.7.4 实现多个接口
- 6.7.5 接口的其他用途
- 6.8 创建和扩展接口
-
- 6.8.1 新接口
- 6.8.2 接口中的方法
- 6.8.3 拓展接口
- 6.8.4 创建网上商店
6.1 限定符
Java语言有很多限定符:
- 限定符public、protected和private:用于控制对类、方法和变量的访问
- 限定符static:用于创造类方法和类变量
- 限定符final:用于固定(finalize)类、方法和变量的实现。
- 限定符abstract:用于创建抽象的类和方法。
- 限定符synchronized和volatile:用于线程
在一条语句中使用多个限定符时,它们的顺序无关紧要,只要位于要限定的元素之前即可。不要将方法的返回类型(如void)看作限定符。返回类型必须位于方法名前面,且在返回类型和方法名之间没有限定符。
控制对方法和变量的访问
可见性 | 公有 | 保护 | 默认 | 私有 |
---|---|---|---|---|
同一个类中 | 是 | 是 | 是 | 是 |
同一个包的任何类中 | 是 | 是 | 是 | 否 |
包外的任何类 | 是 | 否 | 否 | 否 |
同一个包中的子类 | 是 | 是 | 是 | 否 |
包外的子类 | 是 | 是 | 否 | 否 |
访问控制和继承
作为通用的规则,覆盖方法时,新方法的访问控制不能比原来的方法更严格,但可以更送。换而言之,在子类中,方法的可见性不能低于它覆盖的方法的可见性。
存取器方法
用存取器方法来提供对私有变量的访问,可以控制该变量将如何被使用。
6.2 静态变量和方法
限定符static用于创建类方法和类变量
6.3 final类、方法和变量
限定符final用于类、方法和变量,指出它们将不会被修改
6.3.1 变量
final变量常常被称为常量(或常量变量),因为它们的值不会改变。对于变量,限定符final通常与static一起使用,这样,该常量将是类变量。
6.3.2 方法
1.将方法声明为final的最常见的原因是,提高类的运行效率。通常,当JVM运行方法时,它首先在当前类中查找该方法,接下来在其超类中查找,并一直沿类层次结构向上查找,直到找到该方法为止。这提供了灵活性,简化了开发工作,但代价是速度较低。
2.如果方法是final的,java编译器便可将其可执行字节码直接放到调用它的程序中,因为该方法不会被子类覆盖而发生变化。
6.3.3 类
在类的声明中使用限定符final可将其指定为不能继承的,
public final class ChatServer{// body of method
}
在创建子类的声明中,final类不能出现在关键字extends的后面。
- 在final类中,所有方法都将是final的,因此声明它们时,无须使用限定符
6.4 抽象类和方法
- 定义类层次结构的过程中,当您确定通用的行为和属性时,有时可能遇到一些永远不会被实例化的类。这样的类用于定义其子类都有的行为和方法。这些类被称为抽象类,是使用限定符abstract来声明。
- 抽象类可以包含常规类能够包含的任何东西,包括构造函数,因为子类可能需要继承这种方法。抽象类也可以包含抽象方法,这时只有方法特征标,而没有实现的方法。这些方法将在抽象类的子类中被实现。
不能在非抽象类中声明抽象方法。如果一个抽象类除抽象方法外什么都没有,则使用接口更合适
6.5 包
要引用其他包中的类,可以使用全名:包名和类名。
java.awt.Font text = new java.awt.Font();
6.5.1 import 声明
- 导入单个类:
import java.util.ArrayList;
- 也可以导入包中的所有类,方法是使用星号(*)代替类名
import java.awt.*;
- 通过使用import static语句,可以通过更简短的方法引用指定类中的变量。
import static java.lang.Math.*;
6.5.2 类名冲突
在不同包中有多个名称相同的类。在导入含相同名称类的包后,Java编译器无法判断语句中引用的是哪个Date类,因此必须像下面那样指定包名:
java.util.Data = new java.util.Date();
6.6 创建自己的包
6.6.1 选择包名
有一个约定是包名不使用大写字母,以便将其与类名区别开来。
6.6.2 创建文件夹结构
6.6.3 将类加入到包中
6.6.4 包和类访问控制
如果没有指定限定符,则类的访问控制为默认级别,即可被同一个包中的其他任何类使用,但在包外不可见,也不可用。通过包保护的类被隐藏在其所在的包中,不能通过名称来导入或引用它。
6.7 接口
6.7.1 单继承存在的问题
对类层次的简化是受到限制的,尤其需要在同一棵继承树的不同分支上同时使用某些行为时。
- Java接口是一组抽象行为,可以被混合到任何类中,从而给它添加超类不支持的行为。
- Java接口只包含抽象方法定义和常量——既没有实例变量,也没有方法实现。
6.7.2 接口和类
在大多数情况下,在可以使用类的地方,也可以使用接口。接口补充并扩展了类的功能,它们几乎被同等对待,但接口不能被实例化:new只能创造非抽象类的实例。
6.7.3 实现和使用接口
要使用接口,可以在类定义中包含关键字implements:
public class AnimatedSign extends Sign implements Runnable{//...
}
实现接口时,必须实现该接口中所有的方法,而不能有选择地实现其中的某些。通过实现接口,您在告诉用户,这个类支持整个接口。
6.7.4 实现多个接口
要在类中包含多个接口,只需将它们的名称用逗号分开即可:
public class AnimatedSign extends Sign implements Runnable,Observer{// ...
}
6.7.5 接口的其他用途
几乎在任何可以使用类的地方,都可以使用接口来代替。
Iterator loop;
当变量的类型被声明为接口时,就只能存储实现了该接口的对象。在这个例子中,可将实现了接口Iterator的任何类的对象存储到变量loop中;由于loop是一个Iterator对象,因此可通过它调用该接口的全部3个方法:hasNext()、next()和remove()。
- 可以将对象强制转换为接口,就像可以将对象强制转换为其他的类那样。
6.8 创建和扩展接口
6.8.1 新接口
要创建新的接口,可以这样声明它:
interface Expandable{// ...
}
上述声明几乎与类定义相同,只是使用的是关键字interface而不是class。接口定义内是方法和变量。
- 接口内的方法定义是公有和抽象的,可以显式地声明这一点,如果没有包括这些限定符,它们将被自动转换为公有和抽象的。不能在接口内将方法声明为私有或保护的
- 除方法外,接口还可以包含变量,但这些变量必须声明为公有、静态和final的(使之成为常量)。
6.8.2 接口中的方法
可以在任何能够使用类名的地方使用接口名。通过将方法参数定义为接口类型,可以创建通用参数,适用于可能使用该接口的任何类。
6.8.3 拓展接口
与类一样,也可以将接口组织成层次接口。当接口继承另一个接口时,子接口将获得父接口中声明的所有方法定义和常量。
- 要扩展接口,可使用关键字extends,就像扩展类一样:
interface PreciselyTrackable extends Trackable{// ...
}
- 另外,不同于类层次,接口层次可以多重继承。(一个接口可以继承任意数量的接口)
6.8.4 创建网上商店
package com.java21days.day6;public class Item implements Comparable {private String id;private String name;private double retail;private int quantity;private double price;Item(String idIn,String nameIn,String retailIn,String qIn){id=idIn;name=nameIn;retail=Double.parseDouble(retailIn);quantity= Integer.parseInt(qIn);if(quantity>400)price=retail*.5D;else if(quantity>200)price = retail*.6D;elseprice =retail*.7D;price =Math.floor(price*100 + .5)/100;}@Overridepublic int compareTo(Object obj) {Item temp=(Item) obj;if(this.price<temp.price){return 1;}else if(this.price>temp.price){return 1;}return 0;}public String getId(){return id;}public String getName(){return name;}public double getRetail(){return retail;}public int getQuantity(){return quantity;}public double getPrice(){return price;}
}
package com.java21days.day6;import java.util.*;public class Storefront {private LinkedList catalog = new LinkedList();public void addItem(String id, String name, String price, String quant) {Item it = new Item(id, name, price, quant);catalog.add(it);}public Item getItem(int i) {return (Item) catalog.get(i);}public int getSize() {return catalog.size();}public void sort() {Collections.sort(catalog);}
}
package com.java21days.day6;public class GiftShop {public static void main(String[] args) {Storefront store = new Storefront();store.addItem("CO1", "MUG", "9.99", "150");store.addItem("CO2", "LG MUG", "12.99", "82");store.addItem("CO3", "MOUSEPAD", "10.49", "800");store.addItem("DO1", "T SHIRT", "16.99", "90");store.sort();for (int i = 0; i < store.getSize(); i++) {Item show = (Item) store.getItem(i);System.out.println("\\nItem ID: " + show.getId() + "\\nName: " + show.getName() + "\\nRetail Price: $" +show.getRetail() + "\\nPrice: $" + show.getPrice() + "\\nQuantity: " + show.getQuantity());}}
}
输出:
Item ID: CO1
Name: MUG
Retail Price: $9.99
Price: $6.99
Quantity: 150Item ID: CO2
Name: LG MUG
Retail Price: $12.99
Price: $9.09
Quantity: 82Item ID: CO3
Name: MOUSEPAD
Retail Price: $10.49
Price: $5.25
Quantity: 800Item ID: DO1
Name: T SHIRT
Retail Price: $16.99
Price: $11.89
Quantity: 90