Java面向对象编程——面向对象编程(3)

继承

继承是面向对象编程的一个重要概念

父类与子类

一个类继承了另一个类,继承的类就是被继承类的子类,被继承的类就是父类。子类拥有父类的所有属性和方法。同一个包的子类可以全部访问父类的属性和方法,可以重写父类的方法,增加属性,但不同包就要看权限修饰符。

子类继承父类要在子类的类名后面使用保留字extends,后面是父类的类名。Object类默认是所有类的父类,不需要使用extends

Java的类只有单继承,即最多只能继承除一个类,当然Object类不算在里面。

父类与子类之间的转换

可以把子类创建的对象看成是父类对象使用,比如所有类创建的对象都可以被当作Object类的对象使用。

可以把父类对象转成子类对象,但需要用(父类类名)强制转型,举例:

Object obj = new String("abcd");
String str = (String) obj;

子类之间不能相互转换。

方法重写与方法重载

方法重载:在同一个类编写多个同名方法
要求:
方法名一样;
参数类型个数或返回值类型要不一样。

方法重写:修改来自另一个类的同名方法
要求:
方法名、形参要一样;
返回值类型和声明异常的类型小于等于父类;
访问权限,子类大于等于父类;

super

保留字super指代的是父类的对象,和this一样,主要在设计类的属性和方法的时候使用。super可以调用父类的属性和方法,通过super();可以调用父类的构造函数。如果子类没有在构造函数里使用super();,编译的时候编译器会加上。

class Animal {
    void eat() {}
}

class Cat extends Animal(){
	Cat(){
		super.this();
	}
	void grow{
		super.eat();
	}
}


final关键字

保留字final修饰类,这个类就不能被其他类继承,意味着这个类的功能不能被扩充,比如String类就不能被继承。

public final class String ...

修饰方法,表明这个方法不能被重写。

修饰变量,这个变量就成为常量。
如果修饰的是属性,常常和static一起使用,这样就可以在作为常量被其他类使用。
比如System类里的in属性就是用static和final修饰的。

   public static final InputStream in;

InputStream类规定了最大值

    private static final int MAX_SKIP_BUFFER_SIZE = 2048;

final属性不能默认初始化和在方法中初始化,可以显式初始化、在代码块初始化、在构造器初始化。在构造器里赋值的话,需要每个构造器都赋值。因为新建对象的时候,final修饰的属性和值都在堆空间里加载了,如果能在方法里赋值的话,就会与之冲突。

如果修饰final的是局部变量,可以修饰形参和方法体内的变量。修饰形参的时候,不能方法体里给形参赋值操作,比如++这种操作就不行,传入实参后,就会成为常量,但如果传入的是一个类,那么类的属性还可以变,只是类本身不能变,即内存地址不能变。

抽象类

使用保留字abstract,相当于给子类创建了一个模板;
抽象类无法实例化;

public abstract class InputStream ...

抽象方法不能有实体;
所有的抽象方法必须在子类被重写,也可以被重载;
所有的抽象方法都只能在抽象类里创建,否则报错;
例如:

    public abstract int read() throws IOException;

抽象类里可以有普通的方法,但无法被调用,因此需要编写方法的实体,比如

    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }

接口

用保留字interface修饰,而不是class类似于抽象类,也是为了创建一个模板,但接口可以多继承,一个类可以继承多个接口,所以接口比抽象类要更加普遍地使用。

接口没有构造函数,只有方法和常量;
接口只能加public权限修饰符,不能加其他权限修饰符;
实现接口的类必须重写接口的全部方法;

public interface Comparable<T> {
    int compareTo(T var1);
}

调用的时候使用“implements”加要调用的接口
举例:

public abstract class AbstractCollection<E> implements Collection<E> 

如果是一个接口继承另一个接口,则用extends关键字

public interface List<E> extends Collection<E> ...

接口内的方法默认由编译器添加publicabstract关键字,最好不要自己添加修饰符,比如 Comparable接口

public interface Comparable<T> {
    int compareTo(T var1);
}

从Java8开始,接口中还有一种默认方法,用保留字default修饰。因为实现接口的类必须重写接口的全部方法,如果过了很长一段时间后再在接口添加方法,那么实现方法的类就无法编译,除非你花很多精力找出来。这时我们就需要使用默认方法。

默认方法可以有方法体,可以不用被重写。

public interface Iterable<T> {
	......
    default void forEach(Consumer<? super T> var1) {
        Objects.requireNonNull(var1);
        Iterator var2 = this.iterator();

        while(var2.hasNext()) {
            Object var3 = var2.next();
            var1.accept(var3);
        }

    }
    ......
}

如果这个类继承了这个接口,继承的父类,那么以父类为准,这就是 “class wins” 原则。如果实现其他接口也有一模一样的方法,必须重写这个方法。

接口中很少使用属性,但使用时不加任何修饰符,由编译器添加public static final三个关键字,如Iterable接口

public interface Iterable<T> {
    Iterator<T> iterator();
    ......
}

多态

子类转换为父类或接口后,调用普通方法依然是调用的子类的方法。

作用:

  • 可以实现用接口管理各个实现类的行为。
  • 解耦:方法的参数可以是一个接口,这样可以选择任意一个实现类放进这个方法。

举例:

public  class User {
public void status() {
        System.out.println("身份");
    }
}

public class Student extends User{
public void status() {
        System.out.println("学生");
    }
}

public class Teacher  extends User{
public void status() {
        System.out.println("老师");
    }
}

public class Test {
    
    public static void main(String[] args) {
        User s1 = new Student(100,"Jerry","art"); //父类引用指向子类对象
        Teacher t1 = new Teacher(100,"Jerry","art");
        status((Student)s1);
        status(t1);}

static public void status(User u) {
        u.status();
    }
}

内存分析

从object类开始创建,一直到最外层的类;

因为所有类的“this”都是指的最外层的类,所有的方法都先从最外层开始调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值