为什么你找不到对象,因为都是抽象的~

引文:

本文将涉及Java中abstract关键字,接口和内部类的语法与细节~

一、abstract

1.1案例引入

需求:现在我们要设计一个Person类一个工作方法,然后让Student类和Teacher类继承Person类,在Student类和Teacher类中重写Person类的工作方法.

public class test {
    public static void main(String[] args) {

    }
}
class Person{
    public void work(){
        System.out.println();
    }
}

class Student extends Person{
    @Override
    public void work() {
        System.out.println("学生正在上课~");
    }
}

class Teacher extends Person{
    @Override
    public void work() {
        System.out.println("老师正在教书~");
    }
}

此时我们发现Person类中的work()方法该写啥呢?貌似写啥都不对,很尴尬。

此时,我们可以将这个方法声明为抽象方法!

于是我们在方法前面加上abstract关键字。

翻译:在非抽象中抽象方法

所以说当一个类中存在抽象方法是,也需要将这个类声明为抽象类!

由于这个抽象方法你不知道咋写,所以语法规则也让你不要再写方法体了!

1.2 abstract使用语法

  1. 用abstract来修饰一份类时,这个类为抽象类

  1. 用abstract来修饰一份方法时,这个类为抽象方法 注意:抽象方法没有方法体!

  1. 抽象类的价值在于让子类继承并实现抽象方法

1.3 abstract使用细节

  1. 抽象类不能实例化,即你不能创建抽象类对象

  1. 抽象类可以没有抽象方法,但抽象方法一定在抽象类中

  1. abstract只能修饰类和方法,不能修饰属性

  1. 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非自己声明为抽象类(打不过就加入)

  1. 抽象方法不能是用private、final、static来修饰,与重写相违背

private: 私有方法无法被子类访问,谈嘛重写呢

final:本来就是为了不让重写才加的

static: 本来写static是为了能用类来直接调用,而abstract是为了让子类重写,而且抽象方法没有方法体,所以从语法层根本不让你过。

二、接口

2.1接口VS抽象类

接口的使用也是为了重写方法。

这不是跟抽象类的使用差不多吗?有啥区别呢?有抽象类不就够了吗

  1. 抽象类也是继承,只是明确了某些方法必须重写,根本还是为了解决代发的复用性和可维护性

  1. 接口更强调设计方法,让其他类去实现这些方法

  1. 抽象类是继承,满数的关系:is - a, 而接口值只满足 like - a

举个例子:坤坤是个人,所以他可以继承Person类,他会唱跳rap篮球,这些是他后天学习得来的,用接口来实现更合理

2.2基本介绍与语法

介绍:接口就是给出一些没有实现的方法(抽象方法),封装到一起,某个类要使用的时候,再实现出来。

语法:

interface MyInterface{ //接口
    //属性
    //方法
    //1.抽象方法 2.默认实现方法 3.静态方法
}

class A implements MyInterface{
    //必须实现接口的抽象方法
}

注意:Jdk8.0后接口可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现

2.3接口使用细节

  1. 接口不能被实例化(与抽象类类似)

  1. 接口中所有的方法都是public的和abstract的,如果你没写,会自动认为。

  1. 如果一个普通类implements了接口,就必须将接口中所有的抽象方法实现。

  1. 抽象类implements了接口,可以不用实现接口的方法

  1. 一个类可以implements多个接口

  1. 接口中的属性会被默认为public static final

  1. 接口不能继承其他类,但能继承接口

三、内部类

3.1基本介绍

简单来说就类套类,是类的五大成员(属性、方法、构造器、代码块、内部类)

class Outer{ //外部类
    class Inner{//内部类
        
    }
}

3.2局部内部类

局部内部类就是放在外部类的方法中的类

显然局部内部类可以访问外部类中所有成员,包括私有的,因为属于本类

那外部内如何访问局部内部类呢?

public class InnerClass{
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.fun();
    }
}

class Outer{ //外部类
    public void fun(){//方法
        class localInner{//局部内部类
            public void say(){
                System.out.println("你好,我是内部局部类~");
            }    
        }
        localInner localInner = new localInner();
        localInner.say();
    }
}

在含有局部内部类的方法中创建对象调用方法,在main方法中再创建外部类的对象调用方法。

注意:当外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,可以使用

外部类.this.成员

3.3匿名内部类

匿名内部类就是没有名字的局部内部类

语法:

new 类或接口(参数列表){

};
public class Test {
    public static void main(String[] args) {

        new Person(){
            @Override
            public void say() {
                System.out.println("我是匿名内部类~");
            }
        }.say();

    }
}

class Person{
    public void say(){
        System.out.println("Hello~");
    }
}

甚至我们还能这样调用!

public class Test {
    public static void main(String[] args) {
        
        Speak speak = new Speak(){
            public void say(){
                System.out.println("嘻嘻~");
            }
        };
        
        speak.say();
        
    }
}

interface Speak{
    public void say();
}

乍一看,咦,这不是接口实例化了吗?其实并没有,但是匿名内部类在作用

我们先看speak这个引用,他的编译类型为Speak,那运行类型呢?就是匿名内部类!

我们可以通过getclass这个方法看到他的“名字”

所以本质上是这样的:Speak speak = new Test$1 implements Speak;

类似于继承中的向上转型。

应用:

需求:假设我们现在想要养一只小狗,我们可以立马命令小狗做事。

class Dog{
    private String name;

    public Dog(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void Doing(Order order){
        order.action();
    }
}

interface Order{
    public void action();
}

如果我们不适用匿名内部类的话,我们每要让小狗做一个事情,就需要实现一个类来实现接口,很麻烦。

但是我们可以使用匿名内部类来简化代码。

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog("小黄");
        dog.Doing(new Order() {
            @Override
            public void action() {
                System.out.println("小狗汪汪叫~");
            }
        });

        dog.Doing(new Order() {
            @Override
            public void action() {
                System.out.println("小狗去睡觉~");
            }
        });


    }
}

对于第四行本质上:Order order = new Test$1 implements Order

由于重写,会执行{}内中action的方法。

十分方便,对于只是用一次的方法可以写成匿名内部类的形式。

3.4成员内部类

成员内部类是定义在外部类的成员位置上

特点:

  1. 可以直接访问外部类中的所有成员(私有也可以)

  1. 可以添加访问修饰符(private....),因为他的地位就是一个成员

  1. 外部其他类访问成员内部类

方法1:

public class Test {
    public static void main(String[] args) {
        AAA aaa = new AAA();
        AAA.BBB bbb = aaa.new BBB();
        bbb.say();
    }
}

class AAA{
    class BBB{
        public int n1 = 10;
        
        public void say(){
            System.out.println("你好~");
        }
    }
}

aaa.new BBB()相当于 把 new BBB()当做是aaa的成员

方法2:

public class A {
    public static void main(String[] args) {
        AAA aaa = new AAA();
        AAA.BBB b = aaa.getBBB();
    }
}

class AAA{
    class BBB{
        public int n1 = 10;

        public void say(){
            System.out.println("你好~");
        }
    }
    
    public BBB getBBB(){
        return new BBB();
    }
}

让这个类返回就行

3.5静态成员内部类

在成员内部类前加上static

特点:

  1. 只能访问外部类的所有静态成员,非静态成员不可访问

  1. 可以添加访问修饰符(private....),因为他的地位就是一个成员

  1. 外部其他类访问成员内部类

public class A {
    public static void main(String[] args) {
        AAA.BBB b = new AAA.BBB(); //不同于非静态的创建
        b.say();
    }
}

class AAA{
    static class BBB{
        public int n1 = 10;

        public void say(){
            System.out.println("你好~");
        }
    }

    public BBB getBBB(){
        return new BBB();
    }
}

因为是静态的,可以直接通过类名直接访问.

本人是java小白,如有问题请指出。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值