Java面向对象三大特性继承性和super关键字
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
目录
友情提醒
先看文章目录大致了解知识点结构直接点击文章目录可以跳转到文章指定位置。
一、Java面向对象的三大特性之继承
继承是一种关系使用extends关键字在两个类或两个接口之间建立的继承关系。 使用implements在类和接口之间建立实现关系。
二、抽象类
2.1抽象类定义
①abstract关键字代表抽象的意思。abstract修饰类就叫抽象类修饰方法就叫抽象方法。
②因为要被继承所以抽象类一定是父类修饰符必须为public或者protected,不能为private和final。
③抽象类中可以有构造方法但是只有它的子类可以实例化对象接口中不可以有构造方法。
④抽象类中可以写所有类的成员变量普通方法构造方法代码块等。
定义格式如下
/*修饰符 abstract class 类名{
修饰符 abstract 返回值类型 方法名称形参列表
}*/
//抽象类
public abstract class Test
{ int a = 10;
static int b = 20;
static{}
{}
//构造方法
public Creature(){};
//抽象方法
public abstract void test();
//main方法
public static void main(String[] args) {
//内部类
new Creature(){
@Override
public void Test2(){}
};
}
}
2.2抽象方法定义
①抽象方法必须在抽象类中。抽象类中可以不写抽象方法。这样抽象类的子类可以不用重写抽象方法比如适配器模式。
②抽象方法没有方法体子类重写抽象方法时才写具体方法体。
③抽象方法修饰符不能为private和final。也不能和static关键字共存。因为被static修饰的函数是静态函数可以直接类名访问和类的对象无关但是调用一个抽象函数是没有意义的。
//抽象方法格式
//修饰符 abstract 返回值类型 方法名称形参列表
//抽象类
public abstract class Test
{
//抽象方法
public abstract void test();
}
2.3类和类之间的继承extends
①单一继承一个类只能直接继承一个父类
class Father
{
public void func(){
System.out.println("Father...func");
}
}
//---------------------------------分割--------------------------------
class Son extends Father
{ @Override
public void func(){
System.out.println("Son...func");
}
public void test(){
//func();
super.func();
}
}
②多重继承继承中父类可以再继承其他类叫做多重继承父类的父类–》父类–》子类。
class A{
void show(){
System .out.println("hahaha");
}
}
class B extends A {
}
class C extends B{
}
class Test{
public static void main(String[] args){
new C().show();
}
}
//打印结果: hahaha
三、接口
3.1接口的定义
①接口不是一个类所以声明接口不能使用class关键字而是使用interface关键字代表接口的意思。
②接口中可以书写的成员和类不同只能书写成员变量和函数
成员变量的修饰符是 public static final
函数的修饰符是 public abstract
public interface Creature
{
//public Creature(){};//不能有构造方法
//成员变量的修饰符是 public static final
public static final int a = 10;
//抽象方法的修饰符是 public abstract
public abstract void Test2();
//默认方法
default void run(){
System.out.println("我会跑");
};
}
3.2接口中方法的定义
①接口中不可以有构造方法无法实例化对象。
②接口中没具体方法
③从JDK8开始为了能对原来的接口扩展新的方法允许接口中可以有默认实现的方法使用default修饰
④接口里有默认方法静态方法抽象方法。实现类对象不能直接调用接口中静态方法只能通过接口名调用。实现类对象可以直接调用接口中的默认方法。
public interface Inter {
//常量
public static final int A_B_C = 123;
double PI = 3.14;
//抽象方法无法调用只能重写
public abstract void func();
//省略写法其实也是抽象方法
void fun();
//默认方法实现类对象可以直接调用接口中的默认方法。
default void method(){
System.out.println("接口中的默认方法");
};
//接口中的静态方法通过接口名调用
public static void run(){
System.out.println("接口中的静态方法");
};
}
3.3接口和类之间的实现(implements )
①单一实现一个类实现一个父接口用implements 关键字
public interface Inter {
//常量
public static final int A_B_C = 123;
double PI = 3.14;
//抽象方法
public abstract void func();
}
//设计类 类实现接口该类称为接口的实现类
class InterImpl implements Inter{
//独有属性
int num = 666;
int A_B_C = 789;
@Override //重写接口中的抽象方法
public void func() {
System.out.println("实现func...");
}
//独有方法
public void show(){
System.out.println("独有方法show...");
}
}
②多实现一个类实现多个父接口的情况
//格式class Bird implements Inter1,Inter2
//这里用包名.接口名其实不写包名也可以
public class Bird implements interface_2.FlyAble, interface_2.JumpAble {
@Override
public void jump() {
System.out.println("小鸟跳呀跳...");
}
@Override
public void fly() {
System.out.println("小鸟飞呀飞...");
}
}
3.4接口与接口之间的继承extends
①接口与接口单继承接口和类之间使用实现implements 而接口与接口之间使用继承extends。
public interface Animal {
public abstract void fly();
}
public interface FlyAble extends Animal {
//抽象方法
public abstract void fly();
default void run(){
System.out.println("我会跑");
};
}
②接口与接口多继承一个接口可以继承多个接口
//一个接口继承多个接口多个接口之间使用逗号隔开:
//子接口拥有所有父接口中的所有抽象函数不用全部重写
/*interface Inter3 extends Inter1,Inter2{
//...
}*/
③接口与接口多重继承多重继承父接口的父接口–》父接口–》子接口。
interface A{
void show();
}
interface B extends A {
}
interface C extends B{
}
class D implements C{
@Override //具体类必须重写了
public void show(){
System.out.println("666");
};
}
3.5子类继承父类同时实现多个接口
先写继承后面再跟接口的实现
/* class 类名 extends 父类名 implements 接口名1,接口名2,...,接口名n{
//...
}*/
interface Inter{
public void show();
}
class Fu{
public void func(){
System.out.printIn("fu");
}
}
class Zi extends Fu implements Inter{
public void show(){
System.out .println("zzzzz");
}
}
四、继承和实现关系下的变量和方法
4.1继承中的成员变量访问
①子类和父类非私有成员变量同名在子类中默认访问子类成员变量。
public abstract class A{
static int a =1;
abstract void show();
}
class B extends A {
static int a =10000;
public static void main(String[] args) {
System.out.println(a);
B b = new B();
b.show();
}
@Override
void show(){
System.out.println("重写父类的抽象方法");
};
}
//打印结果
//10000
//重写父类的抽象方法
4.2继承中的方法调用
①子类和父类非私有成员方法同名默认调用子类方法。
public abstract class A{
abstract void show();
public void func(){
System.out.println("父类普通方法");
}
}
class B extends A {
public static void main(String[] args) {
B b = new B();
b.show();
b.func();
}
@Override
void show(){
System.out.println("重写父类的抽象方法");
};
@Override
public void func(){
System.out.println("子类重写父类普通方法");
}
}
//打印结果
//重写父类的抽象方法
//子类重写父类普通方法
4.3使用Super关键字
super用法
①super在普通方法中用这个关键字去执行被重载的超类中的非静态方法使用super.func()去调用超类中被重载的方法。
ps:重写父类方法的时候可以在子类方法体里直接super.父类方法直接把父类方法拿过来用然后再添加其他代码达到复用的目的。
class Father
{ public void func(){
System.out.println("Father...func");
}
}
//---------------------------------分割--------------------------------
class Son extends Father
{ public void func(){
System.out.println("Son...func");
}
public void test(){
//func();
super.func();
}
}
②super关键字在构造方法子类构造方法首行隐式的有super()用来接受父类成员变量先调用父类构造再调用子类构造。 对super的调用必须是构造器中的第一个语句。this() 和 super() 不能同时存在因为他们都要写在构造函数的第一行。
class Person
{
//属性
String name;
int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public Person(){ }
}
//------------------分割--------------------------------------
class Worker extends Person
{
//方式一显示定义在构造方法内部调用super(...)构造
public Worker(String name,int age){
super(name,age);
}
//方式二在Person类中有空参构造本类的空参构造隐式的有super()
public Worker(){
//super();//可以不写
}
}
③父类和接口中如果都定义了相同名字的默认方法子类继承父类的同时实现了该接口默认执行父类中的方法这是类优先原则如果想使用接口中的方法接口名.super.方法名。
④两个接口中都定义了相同名字的默认方法子类同时实现两个接口这时候编译器报错需要选择一下具体用哪个或者用接口名.super.方法名来选择再或者直接全部重写。
public interface Inter2 {
//默认方法1
public default void method(){
System.out.println("Inter2...method");
}
//默认方法2
public default void func(){
System.out.println("Inter2...func");
};
//抽象方法
void show();
}
//-------------------------------分割------------------------------
public interface Inter3 {
//默认方法1
public default void method(){
System.out.println("Inter3...method");
}
//默认方法2
public default void func(){
System.out.println("Inter2...func");
};
//抽象方法
void show();
}
//-------------------------------分割------------------------------
/* 接口冲突问题
* 多个接口内部都定义了相同名字的默认方法类同时去实现这多个接口
* 用接口名.super.方法名来选择再或者直接全部重写。
*/
public class InterImpl2 implements Inter2, Inter3 {
@Override//重写默认方法
public void method() {
// Inter2.super.method();
// Inter3.super.method()
System.out.println("都不适合完全重写...");
}
@Override//重写默认方法
public void func() {
Inter2.super.func();
// Inter3.super.func()
// System.out.println("都不适合完全重写...");
}
@Override//重写抽象方法
public void show() {
System.out.println("sbsbsb");
}
}
4.4继承/实现关系下的重写
方法的重写
①重写override也称覆盖。重写是子类对父类非静态非private非final非构造方法的实现过程进行重新编写重写的目的在于根据对象的类型不同而表现出多态而静态方法不需要创建对象就可以使用。没有了对象重写所需要的“对象的类型”也就没有存在的意义了。
②修饰符返回值类型方法名参数列表要完全一致返回值JDK7以后被重写的方法返回值类型可以不同但是必须是具有父子关系的即外壳不变核心重写。
③重写的方法不能使用限制更严格的访问权限修饰符。比如被重写的方法修饰符是 protected那么重写的方法只能是 protected 或者 public修饰。
④重写后的方法不能抛出比父类中更高级别的异常。
⑤子类中通过 super 关键字来调用父类中被重写的方法。
⑥分四点
1.子类继承普通类并非一定要重写父类方法
2.子类继承抽象类子类是抽象类不要求重写父类方法。子类是普通类要重写全部抽象方法。
3.子接口继承父接口。子接口可以继承父接口的所有常量和抽象方法子接口还可以继承其他父接口也就是可以扩展父接口的方法
4.如果是一个子抽象类可以部分或全部实现父接口的方法如果子类是具体类则要求子类一定要实现父接口中定义的所有方法接口中的所有方法均为抽象方法。
public abstract class A{
abstract void show();
public void func(){
System.out.println("父类普通方法");
}
}
class B extends A {
public static void main(String[] args) {
B b = new B();
b.show();
b.func();
}
@Override
void show(){
System.out.println("重写父类的抽象方法");
};
@Override
public void func(){
System.out.println("子类重写父类普通方法");
}
}
//打印结果
//重写父类的抽象方法
//子类重写父类普通方法
4.5继承关系下的执行优先级
父类的静态代码块和静态属性>子类的静态代码块和静态属性>父类的构造代码块和普通属性初始化>父类构造方法>子类的构造代码块和普通属性初始化>子类的构造方法
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |