Java学习笔记(三)

…衆ロ難τιáo~ 提交于 2020-02-17 17:34:31

继承(子类 is a 父类)

//父子类有成员变量,成员函数重名(覆盖 重写)时。创建的对象是谁,就优先用谁。如果没有,则向上找。
//@override: 检测是否是正确的覆盖重写

public class Extends {

    public static void main(String[] args) {

        Teacher teacher = new Teacher();
        teacher.method();   //父类方法执行
        teacher.methodT();  //30 20 10

        Assistant ass = new Assistant();
        ass.method();   //父类方法执行
        ass.methodE();  //子类运行方法e

    }


}

//父类
class Employee {

    int num = 10;

    public void method() {
        System.out.println("父类方法执行");
    }

    public void methodE() {
        System.out.println("父类运行方法e");
    }
}

//子类1
class Teacher extends Employee{

    int num = 20;
    public void methodT(){

        int num = 30;

        System.out.println(num);    //30
        System.out.println(this.num);   //20
        System.out.println(super.num);  //10
    }

}

//子类2
class Assistant extends Employee{

    @Override
    public void methodE() {
        System.out.println("子类运行方法e");
    }
}

继承关系中的构造函数

/*
1.子类构造方法中有一个隐含的“super()”调用,所以一定是先执行父类构造,后执行子类构造。
2.子类构造可以通过super关键字调用父类重载构造。
3.super的父类构造调用,必须放在子类构造方法的第一个语句。
总结:
子类必须调用父类且在最前面调用父类构造,不写默认赠送“super()”,写了则用指定的super调用。
 */
public class ExtendsConstructor {

    public static void main(String[] args) {
        Zi zi = new Zi();
    }
}

class Fu {

    public Fu(int num) {

        System.out.println("父类有参构造");
    }
}

class Zi extends Fu {

    public Zi() {
        super(10);
        System.out.println("子类构造");
    }
}

抽象(abstract)

public class Abstract {

    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.eat();

        Dog2ha ha = new Dog2ha();
        ha.sleep();
    }
}

//有抽象方法的一定是个抽象类
abstract class Animal {

    public abstract void eat();
    public abstract void sleep();
}

class Cat extends Animal {
    @Override
    public void eat(){
        System.out.println("fish");
    }

    @Override
    public void sleep(){
        System.out.println("miaomiaomiao");
    }
}

//抽象类不一定有抽象方法(该子类还有子类,抽象方法在孙子类中实现)
abstract class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("bone");
    }
}

class Dog2ha extends Dog {

    @Override
    public void sleep() {
        System.out.println("hahaha");
    }
}

class DogGolden extends Dog {

    @Override
    public void sleep() {
        System.out.println("huhuhu");
    }
}

接口(interface)

接口中抽象方法和默认方法
/*
接口就是多个类的公共规范。
是一种引用类型,最重要的内容就是其中的,抽象方法。
 */

/*
接口中定义抽象方法:
修饰符必须是两个关键字:public abstract,但可以选择性省略不写

接口中定义默认方法:(可以解决接口升级的问题)
修饰符为关键字:public default,public可以省略
 */
interface MyInterfaceAbstract {

    //这是一个抽象方法
    public abstract void method1();

    //这也是抽象方法
    public void method2();

    //这也是抽象方法
    abstract void method3();

    //这也是抽象方法
    void method4();

    //这是一个默认方法
    default void methodDefault(){
        System.out.println("接口中的默认方法");
    }
}

/*
接口的使用:
接口不能直接使用,必须定义一个“实现类”。
实现类必须覆盖重写接口中所有的抽象方法
如果实现类没有重写所有的抽象方法,那么这个实现类自己必须是一个抽象类

接口中的默认方法,可以通过接口实现类对象直接调用,也可以被实现类对象覆盖重写
 */
class MyInterfaceAbstractImpl implements MyInterfaceAbstract {

    @Override
    public void method1() {
        System.out.println("方法一");
    }

    @Override
    public void method2() {
        System.out.println("方法二");
    }

    @Override
    public void method3() {
        System.out.println("方法三");
    }

    @Override
    public void method4() {
        System.out.println("方法四");
    }

    /*
    @Override
    public void methodDefault() {
        System.out.println("重写的默认方法");
    }
    */
}


public class DemoInterface {

    public static void main(String[] args) {
        MyInterfaceAbstractImpl impl = new MyInterfaceAbstractImpl();
        impl.method1();
        impl.method2();
        impl.methodDefault();
    }
}
接口中的静态方法
/*
接口中的静态方法不能通过实现类的对象来调用,只能通过接口名称直接调用
 */
interface Interface {

    static void methodStatic(){
        System.out.println("接口中的静态方法");
    }

}

class InterfaceImpl implements Interface {

}

public class DemoInterface1 {

    public static void main(String[] args) {

        InterfaceImpl impl = new InterfaceImpl();

        //错误写法
        //impl.methodStatic();

        //正确写法
        Interface.methodStatic();
    }
}
接口中私有方法和常量
/*
接口中的私有方法:
问题描述:
我们需要抽取一个公共方法,用来解决两个默认方法的代码重复问题。
但这个方法不应该让实现类使用,应该是接口内私有化的。

解决方法:
1.普通私有方法:解决多个默认方法之间代码重复问题
2.静态私有方法:解决多个静态方法之间代码重复问题
 */
/*
接口中的常量:
接口中可以定义成员变量,但有public static final 三个关键字进行默认修饰(可以省略不写),
从效果上看,这其实是接口的“常量”。且必须进行明确地赋值。
常量名称使用完全大写字母,中间用下划线分隔(推荐写法)。
 */
interface Interface2 {

    public static final int NUM_OF_CLASS = 10;

    default void method1(){
        System.out.println("一");
        methodCommon();
    }

    default void method2(){
        System.out.println("二");
        methodCommon();
    }

    //普通私有方法
    private void methodCommon(){
        System.out.println("一二");
    }

    static void methodSta1(){
        System.out.println("static1");
        methodStaticCommon();
    }

    static void methodSta2(){
        System.out.println("static2");
        methodStaticCommon();
    }

    //静态私有方法
    private static void methodStaticCommon(){
        System.out.println("static12");
    }
}

class InterfaceImpl2 implements Interface2 {

}

public class DemoInterface2 {

    public static void main(String[] args) {

        InterfaceImpl2 impl = new InterfaceImpl2();

        impl.method2();
        Interface2.methodSta1();

        System.out.println(Interface2.NUM_OF_CLASS);
    }
}
接口注意事项
/*
接口的注意事项:

1.接口没有静态代码
2.接口没有构造方法
3.一个类只能有一个直接父类,但可以有多个接口
    public class MyInterfaceImpl implements InterfaceA, InterfaceB {
        //覆盖重写所有的抽象方法
    }
4.实现类的多个接口中存在重复抽象方法,只需覆盖重写一次
5.如果没有全部重写抽象方法,实现类就必须是一个抽象类
6.实现类的多个接口存在重复的默认方法,一定要对此方法进行重写
7.一个类的直接父类中的方法和接口中的默认方法冲突,优先使用父类中的方法
8.一个接口可以多继承
    public Interface MyInterface extends InterfaceA, InterfaceB{}
 */

多态(multi)

/*
多态性:父类引用子类对象(向上转型)

格式:
父类名称 对象名 = new 子类名称();
接口名称 对象名 = new 实现类名称();
 */
public class DemoMulti {

    public static void main(String[] args) {

        Fu obj = new Zi();

        obj.method();   //成员方法看new的是谁,输出“子类方法”
        obj.methodFu(); //"父类特有方法"

        System.out.println(obj.num);    //成员变量看等号左边是谁,输出“10”
    }
}

class Fu {

    int num = 10;

    void method(){
        System.out.println("父类方法");
    }

    void methodFu(){
        System.out.println("父类特有方法");
    }
}

class Zi extends Fu {

    int num = 20;

    void method(){
        System.out.println("子类方法");
    }
}
多态的向下转型与instanceof
/*
多态的向下转型:
其实是一个还原动作,当子类需要访问自己独有的成员方法时,需要向下还原为子类类型

格式:
子类名称 对象名 = (子类名称) 父类对象

举个例子:
Animal ani = new Cat(); //本来是猫,向上转型为动物
Cat cat = (Cat) ani; //本来是猫,已经被当成是动物,还原回猫

向下转型时有时会不确定父类对象对应哪一子类,解决方法:
instanceof
例子:
public void giveMeAPet (Animal ani) {

    if(ani instanceof Dog) {
        Dog dog = (Dog) ani;
        dog.watchHouse()
    }
    if(ani instanceof Cat) {
        Cat cat = (Cat) ani;
        cat.catchMouse()
    }
    
} 
*/

内部类

/*
成员内部类:
1.间接方式:在外部类的方法中使用内部类,然后再main中调用外部类方法
2.直接方式:外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称()

局部内部类:
在成员方法中定义类,创建对象等对内部类的一系列操作。main中只调用该成员方法
 */

/*
内部类访问外部类重名变量:
外部类名称.this.重名变量名称
 */

//外部类
class Body {

    int num = 10;

    //成员内部类
    public class Heart {

        public void methodHeart(){
            System.out.println("成员内部类方法");
        }

        int num = 20;

        public void methodNum(){
            int num = 30;
            System.out.println(num);    //30
            System.out.println(this.num);   //20
            System.out.println(Body.this.num);  //10
        }

    }

    public void methodOuter(){

        //局部内部类
        class Inner {
            int num = 10;
            public void methodInner() {
                System.out.println(num);
            }
        }
        Inner inner = new Inner();
        inner.methodInner();
    }

    public void methodBody() {
        System.out.println("外部类方法");
    }

    public void bodyHeart() {
        Heart heart = new Heart();
        heart.methodHeart();
    }
}
public class DemoInnerClass {

    public static void main(String[] args) {

        //间接方法
        Body body = new Body();
        body.bodyHeart();
        body.methodOuter();

        //直接方法
        Body.Heart heart = new Body().new Heart();
        heart.methodHeart();
        heart.methodNum();
    }
}
匿名内部类
/*
使用场景:如果接口的实现类(或者父类的子类)只需要使用唯一一次
    那么这种情况就可以省略掉该类的定义,而改为使用【匿名内部类】

注意:
1.匿名内部类在创建对象的时候,只能使用唯一一次,如果需要多次创建对象
    且内容一样的话,就必须使用单独定义的实现类了

 */

interface MyInterface {
    public void method();
}

public class NImingInnerClass {

    public static void main(String[] args) {

        //匿名内部类
        MyInterface obj = new MyInterface() {
            @Override
            public void method() {
                System.out.println("匿名内部类实现了方法");
            }
        };
        obj.method();
    }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!