继承
Object
Java中,Object
类是所有类的父类。
因此,所有类都继承了Object
类的方法,如getClass()
、hashCode()
、toString()
、equals()
。
public class Animal {
private String picture;
public void roam(){
System.out.println("Animal: roaming");
}
}
public class Dog extends Animal {
public void roam(){
System.out.println("Dog: roaming");
}
}
public class Hippo extends Animal {
public void roam(){
System.out.println("Hippo: roaming");
}
}
public class Test {
public static void main(String[] args){
Dog d = new Dog();
System.out.println("d.getClass(): " + d.getClass());
System.out.println("d.hashCode(): " + d.hashCode());
System.out.println("d.toString(): " + d.toString());
System.out.println("");
Hippo h = new Hippo();
System.out.println("h.getClass(): " + h.getClass());
System.out.println("h.hashCode(): " + h.hashCode());
System.out.println("h.toString(): " + h.toString());
System.out.println("");
if(d.equals(h)){
System.out.println("true");
}else{
System.out.println("false");
}
}
}
- Java不允许多重继承
子类只能继承一个父类,不能继承多个父类 - 使用
super
获取父类
super.roam()
public class Animal {
private String picture;
public void roam(){
System.out.println("Animal: roaming");
}
}
public class Hippo extends Animal {
public void roam(){
super.roam();
System.out.println("Hippo: roaming");
}
}
public class Test {
public static void main(String[] args){
Hippo h = new Hippo();
h.roam();
}
}
- 通过
super()
调用父类的构造函数
父类的构造函数必须在子类的构造函数之前调用。
public class Animal {
public Animal(){
System.out.println("making an animal");
}
}
public class Hippo extends Animal {
public Hippo(){
super();
System.out.println("Step 2: making a hippo");
}
}
public class Test {
public static void main(String[] args){
Hippo hippo = new Hippo();
}
}
public class Animal {
private String name;
public Animal(String theName){
name = theName;
}
public String getName(){
return name;
}
}
public class Hippo extends Animal {
public Hippo(String name){
super(name);
}
}
public class Test {
public static void main(String[] args){
Hippo hippo = new Hippo("Jeff");
System.out.println(hippo.getName());
}
}
- 通过
this()
在构造函数中调用同类的另一个构造函数
this()
只能在构造函数中使用,且必须放在第一行;
this()
和super()
不能同时使用。
public class Animal {
private String name;
public Animal(){
this("Tom");
}
public Animal(String theName){
name = theName;
}
public String getName(){
return name;
}
}
public class Hippo extends Animal {
public Hippo(String name){
super(name);
}
}
public class Dog extends Animal {
}
public class Test {
public static void main(String[] args){
Hippo hippo = new Hippo("Jeff");
System.out.println("hippo'name is "+hippo.getName());
Dog dog = new Dog();
System.out.println("dog's name is "+ dog.getName());
}
}
- 访问权限
public
protected
private
- 如何让类不可被继承
- 使用
final
修饰类
比如,public final class Animal{}
。
另外,final
也可以用来修饰类的方法,从而防止方法被覆盖。 - 将类的构造函数标记为
private
比如,private Animal(){}
- 使用
- 方法覆盖
- 参数类型必须相同,返回值类型必须兼容
- 不能降低访问权限
多态
public class Animal {
private String picture;
public void roam(){
System.out.println("Animal: roaming");
}
}
public class Dog extends Animal {
public void roam(){
System.out.println("Dog: roaming");
}
}
public class Test {
public static void main(String[] args){
Dog d = new Dog();
d.roam();
Animal dog = new Dog();
dog.roam();
}
}
抽象类
public class Animal {
private String picture;
public void roam(){
System.out.println("Animal: roaming");
}
}
public class Dog extends Animal {
public void roam(){
System.out.println("Dog: roaming");
}
}
public class Hippo extends Animal {
public void roam(){
super.roam();
System.out.println("Hippo: roaming");
}
}
public class Test {
public static void main(String[] args){
Dog dog = new Dog();
dog.roam();
Hippo hippo = new Hippo();
hippo.roam();
Animal animal = new Animal();
animal.roam();
}
}
创建出Dog
对象、Hippo
对象很合理,但Animal
对象却有些出人意料,它应该长什么样?几条腿?
也就是说Animal
类不应该被初始化。
类 Dog
、类Hippo
是具体类,可以被初始化为对象;
类Animal
,则是抽象类,不应该被初始化的类,用abstract
修饰。
public abstract class Animal {
private String picture;
public void roam(){
System.out.println("Animal: roaming");
}
}
public class Test {
public static void main(String[] args){
Animal animal = new Animal();
}
}
抽象方法
- 抽象方法没有实体
- 抽象方法必须在抽象类中声明
- 继承了抽象类的子类必须实现抽象类中的抽象方法,即抽象方法必须被覆盖
- 抽象类中既可以有抽象方法,也可以有非抽象方法
public abstract class Animal {
private String picture;
public abstract void eat();
public void roam(){
System.out.println("Animal: roaming");
}
}
public class Dog extends Animal {
public void roam(){
System.out.println("Dog: roaming");
}
}
public class Hippo extends Animal {
public void roam(){
System.out.println("Hippo: roaming");
}
}
public class Test {
public static void main(String[] args){
}
}
public abstract class Animal {
private String picture;
public abstract void eat();
public void roam(){
System.out.println("Animal: roaming");
}
}
public class Dog extends Animal {
public void eat(){
System.out.println("Dog eat bone");
}
public void roam(){
System.out.println("Dog: roaming");
}
}
public class Hippo extends Animal {
public void eat(){
}
public void roam(){
System.out.println("Hippo: roaming");
}
}
public class List {
private Animal[] list = new Animal[5];
private int nextIndex = 0;
public void add(Animal a){
if(nextIndex < list.length){
list[nextIndex] = a;
System.out.println("Add animal at " + nextIndex);
nextIndex++;
}
}
}
public class Test {
public static void main(String[] args){
List list = new List();
Dog d = new Dog();
list.add(d);
Hippo h = new Hippo();
list.add(h);
}
}
接口
- 所有方法都是抽象的
抽象类既可以有抽象方法,也可以有非抽象方法。
接口,可以理解成100%的抽象类,即所有的方法都是抽象的。 - 定义接口
定义接口用interface
- 实现接口
实现接口用implements
public class Animal {
private String picture;
public void eat(){
System.out.println("Animal:eat something");
}
}
public class Canine extends Animal{
public void roam(){
System.out.println("Canine:roam");
}
}
public interface Pet {
void play();
void beFriendly();
}
public class Dog extends Canine implements Pet {
public void eat(){
System.out.println("Dog: eat bone");
}
public void play(){
System.out.println("Dog: play");
}
public void beFriendly(){
System.out.println("Dog: be friendly");
}
}
public class Test {
public static void main(String[] args){
Dog dog = new Dog();
dog.eat();
dog.roam();
dog.play();
dog.beFriendly();
}
}
接口里声明的方法默认是public
和abstract
,所以上面就省写了,当然也可以像下面这样都写上,
public interface Pet{
public abstract void play();
public abstract void beFriendly();
}
静态方法
- 静态方法用
static
标记 - 静态方法通过类名来调用
静态变量是通过类名来调用的,而不是通过实例来调用的,静态方法不依赖于实例变量。也正因为此,静态方法中不能调用非静态变量,或者说,静态方法中不能使用实例变量。如果在静态方法中使用实例变量,编译器会因为不知道到底使用哪个实例的变量而报错。
同样,静态方法中不能调用非静态方法,因为非静态方法依赖于实例变量。
静态变量
静态变量由所有实例共享。
静态变量通过类名来访问。
public class Player {
private String name;
public static int playerCount = 0;
public Player(String theName){
name = theName;
playerCount++;
}
}
public class Test {
public static void main(String[] args){
System.out.println(Player.playerCount);
Player one = new Player("Tom");
System.out.println(Player.playerCount);
Player two = new Player("John");
System.out.println(Player.playerCount);
}
}
final
用final
标识的变量,不能被修改;
用final
标识的方法,不能被覆盖;
用final
标识的构造函数,该构造函数所在类不能被继承,也不能创建该类的实例。
static final变量
用static
修饰的final
变量是常数。
static final变量的初始化
static final
变量有以下两种初始化方式。
- 第一种:声明时赋值
public class Test {
public final static double PI = 3.141592;
}
- 第二种:在静态初始化程序中赋值
静态初始化程序在加载类时执行,且在该类的其他所有代码之前执行。
public class Test {
public static final double PI;
static {
PI = 3.141592;
}
}
方法重载
函数名相同,参数不同。参数个数不同或参数类型不同。