首页 > 其他 > 详细

面向对象:抽象类与接口、内部类、枚举类

时间:2019-06-17 09:10:54      阅读:110      评论:0      收藏:0      [点我收藏+]

抽象类

抽象方法与抽象类必须使用abstract修饰符来定义,有抽象方法的类只能被定义成抽象类,抽象类可以没有抽象方法。

抽象方法和抽象类的规则:抽象类必须使用abstract修饰符来修饰,抽象方法也必须使用abstract修饰符修饰,抽象方法不能有方法体;抽象类不能实体化,无法使用new关键字调用抽象类的构造器创建抽象类的实例。抽象类不包含抽象方法也不能实例化;抽象类可以包含成员变量、方法(普通方法和抽象方法都可以)、构造器、初始化块、内部类(接口和枚举)5成分。抽象类的构造器不能实例化,只能用于被子类调用;含有抽象方法的类(包括直接定义了一个抽象方法,或者继承一个抽象父类但没有完全实现父类包含的抽象方法;实现一个接口,但没有完全实现接口包含的抽象方法三种情况)只能被定义成抽象类。

abstract class abstractClass{
    {
        System.out.println("abstractClass初始化块");
    }
    String name;
    //抽象方法
    //抽象方法没有方法体,不能用private修饰,抽象方法就是为了重写的
    public abstract void test();
    public abstract void test2(String name);
}
public class AbstractClassSon extends abstractClass{
    public void test(){
        System.out.println("子类重写抽象类不带参数的抽象方法");
    }
    public void test2(String name){
        System.out.println("子类重写抽象类带参数的抽象方法,参数值为: " + name);
    }
    public static void main(String[] args){
        AbstractClassSon acs = new AbstractClassSon();
        acs.test();
        acs.test2("lilei");
    }
}

final不能与abstract同时使用,final修饰的不能被重写,抽象类就是为了重写。

abstract不能修饰成员变量,也不能修饰局部变量,没有抽象变量、抽象成员变量的说法;abstract也不能修饰构造器,没有抽象构造器的说法。

static和abstract不能同时使用,没有静态抽象方法。static修饰的方法是类方法,abstract修饰的方法是要被重写的,当抽象类没有被重写无法用一个不存在的方法调用类方法。但abstract和static不能互斥的,它们可以修饰内部类。

abstract关键字修饰的方法必须被子类重写才有意义,因此abstract修饰的方法不能定义为private访问权限。

抽象类不能创建实例,只能当成父类来创建。从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的模板,从而避免了子类设计的随意性。

接口

抽象类是从多个类中抽象出来的模板,如果将这种抽象进行得更彻底,则可以提炼出一种更加特殊的抽象类-接口,接口中不能含有普通方法,接口中所有方法都是抽象方法。Java8进行了改进,允许定义默认方法,默认方法提供方法的实现。

一个接口可以有多个父接口,但接口只能继承接口不能继承类

interface 接口名 extends 父接口 implements 接口1, 接口2.。。

由于接口定义的是一种规范,所以接口不能包含构造器和初始化块。接口里可以包含成员变量(只能是静态变量)、方法(只能是抽象方法、类方法或默认方法)内部类(内部接口、枚举)

接口中所有成员都是public访问权限,接口中定义的静态常量而言,它们是接口相关的,因此系统会自动为这些成员变量添加static 和final修饰符。接口中定义成员变量系统会自动帮你添加public static final修饰符。接口定义的成员变量只能在定义时指定默认值。

public static final int MAX_SIZE = 36E;

接口定义的方法只能是抽象方法、类方法或默认方法,因此如果不是定义默认方法,系统将自动为普通方法添加abstract修饰符。接口中普通方法不能有方法实现,但类方法、默认方法都必须有方法实现。

interface InterfaceClass{
    //抽象方法
    public abstract void abstractMethod();
    //默认方法
    default void defaultMethod(){
        System.out.println("接口中的默认方法");
    }
    //接口的类方法
    static void staticMethod(){
        System.out.println("接口中的类方法");
    }
}
public class InterfaceTest implements InterfaceClass{
    //冲写接口的抽象方法
    public void abstractMethod(){
        System.out.println("重写接口的抽象方法");
    }
    public static void main(String[] args){
        InterfaceTest it = new InterfaceTest();
        it.abstractMethod();
        it.defaultMethod();
        //staticMethod();
    }
}

接口完全支持多继承

interface ExtendsInterface{
    int i = 10;
    public abstract void father1Method();
}

interface ExtendsInterface2{
    int j = 20;
    public abstract void father2Method();
}

interface InterfaceClass extends ExtendsInterface, ExtendsInterface2{
    //接口可以多继承
}
public class InterfaceTest2 implements InterfaceClass{
    public void father1Method(){
        System.out.println("father1的抽象方法");
    }
    public void father2Method(){
        System.out.println("father2的抽象方法");
    }
    public static void main(String[] args){
        InterfaceTest2 it = new InterfaceTest2();
        System.out.println("i = " + it.i);
        System.out.println("j = " + it.j);
        it.father1Method();
        it.father2Method();
    }
}

一个类使用extends继承,但只能继承一个类;使用implements实现多个接口。实现接口的方法,必须用public访问控制修饰符。

接口不能显式继承任何类,但所有接口类型的引用变量都可以直接赋给Object类型的引用变量。

接口和抽象类共同点:接口和抽象类不能被实例化,他们位于继承树的顶端,用于被其他类实现和继承;接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类必须实现这些方法。

不同点:接口只能包含抽象方法、静态方法、默认方法,抽象类可以是包含普通方法;接口只能定义静态常量,不能定义普通成员变量,抽象类都可以;接口不包含构造器,抽象类可以包含;接口不包含初始化块,抽象类可以;一个类只能有一个直接父类,但可以实现多个接口。

内部类

把一个类放在另一个类的内部定义,成为内部类。

内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许统一包中其他类访问该类;内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员可以互相访问,但外部类不能访问内部类的实现细节;匿名内部类适合用于创建仅需要使用一次的类。

public class outClass{
  //定义内部类  
}

 

大部分时候,内部类都被作为成员内部类定义,而不是局部内部类。成员内部类是一种与成员变量、方法、构造器和初始化块相似的类成员;局部内部类和匿名内部类则不是类成员。

成员内部类分为两种:静态内部类和非静态内部类,静态内部类使用static修饰

public class InnerClass{
    private String name;
    public InnerClass(String name){
        this.name = name;
    }
    //内部类
    public class NBLClass{
        private int age;
        private String color;
        public NBLClass(){}
        public NBLClass(int age, String color){
            this.age = age;
            this.color = color;
        }
        public void info(){
            System.out.println("age = " + age +  "  color = " + color);
            System.out.println("访问外部类private修饰的成员变量,name的值为" + name);
        }
    }
    public void test(){
        NBLClass nblc = new NBLClass(18, "green");
        nblc.info();
    }
    
    public static void main(String[] args){
        InnerClass ic = new InnerClass("lilei");
        ic.test();
    }
    
}

把这个类的定义放在另一个类的内部,所以就成了一个内部类,可以使用private修饰符修饰这个类

private class NBLClass{
        private int age;
        private String color;
        public NBLClass(){}
        public NBLClass(int age, String color){
            this.age = age;
            this.color = color;
        }
        public void info(){
            System.out.println("age = " + age +  "  color = " + color);
            System.out.println("访问外部类private修饰的成员变量,name的值为" + name);
        }
    }
    public void test(){
        NBLClass nblc = new NBLClass(18, "green");
        nblc.info();
    }

如果外部类成员变量、内部类成员变量与内部类里的方法的局部变量同名,则可通过this、外部类类名.this作为限定区分

public class InnerClass{
    private String name;
    public InnerClass(String name){
        this.name = name;
    }
    //内部类
    private class NBLClass{
        private String name;
        public NBLClass(String name){
            this.name = name;
        }
        public void info(String name){
            System.out.println(name);
            System.out.println(this.name);
            System.out.println(InnerClass.this.name);

        }
    }
    public void test(){
        NBLClass nblc = new NBLClass("内部类的成员变量");
        nblc.info("内部类的局部变量");
    }
    
    public static void main(String[] args){
        InnerClass ic = new InnerClass("外部类的成员变量");
        ic.test();
    }
    
}

外部类要访问非静态内部类的成员,必须显式创建非静态内部类对象类调用访问其实例成员

public class InnerClass{
    private int age = 100;

    //内部类
    private class NBLClass{
        private int InnerAge = 200;
        public void info(){
            System.out.println("外部类age的值: " + age);

        }
    }
    public void test(){
        //外部类访问非静态内部类必须显式创建内部类的实例,再调用变量
        System.out.println("内部类InnerAge的值" + new NBLClass().InnerAge);
    }
    
    public static void main(String[] args){
        InnerClass ic = new InnerClass();
        ic.test();
    }
    
}

非静态内部类对象必须寄生在外部类对象中,而爱不累对象则不必一定有非静态内部类对象寄生其中。如果存在一个非静态内部类对象,则一定存在一个被它寄生的外部类。

Java不允许非静态内部类定义静态成员。非静态内部类不能有静态初始化块,但可以包含普通初始化块。非静态内部类普通初始化块的作用与外部类初始化块的一样。

静态内部类可以包含静态成员,也可以包含非静态成员。根据静态不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。

public InnerStaticClass{
    private static int i = 100;
    
    static class InnerClass{
        private static int j = 200;
        public void test(){
            System.out.println("静态内部类只能访问外部类的静态成员: " + i);
    }
}

 

静态内部类是外部类的一个静态成员,因此外部类的所有方法,所有初始化块可以使用静态内部类类定义变量、创建对象等。

外部类不能直接访问静态内部类的成员,但可以使用静态内部类的类名作为调用者来访问内部类的类成员,也可以使用静态内部类对象作为调用者访问。

public class InnerStaticClass{
    
    static class InnerClass{
        private static int j = 100;
        private static int i = 200;
    }
    public static void main(String[] args){
        //使用静态内部类类名访问变量
        System.out.println(InnerClass.i);
        //创建静态内部类对象访问变量
        System.out.println(new InnerClass().j);
    }
}

Java还允许接口里定义内部类,皆苦定义的内部类默认使用public static 修饰。也就是接口内部类只能是静态内部类。

在外部类中使用内部类和普通类没什么区别,需要注意的是不能在外部类的静态成员中使用非静态内不来,静态成员不能访问非静态成员。

在外部类以外使用非静态内部类,则内部类不能用private修饰,private修饰只能在外部类中使用。

class InnerClass{
    class In{
        public In(String name){
            System.out.println(name);
        }
    }
}

public class OutClass{
    public static void main(String[] args){
        //外部类以外访问内部类
        //非静态内部类的构造器碧玺使用外部类对象调用
        InnerClass.In icin = new InnerClass().new In("lilei");
    }
}

在外部类以外使用静态内部类

class InnerClass{
    static class In{
        public In(String name){
            System.out.println(name);
        }
    }
}

public class OutClass{
    public static void main(String[] args){
        //外部类以外访问静态内部类
        InnerClass.In icin = new InnerClass.In("lilei");
    }
}

其中new InnerClass.In()这里是类名.静态成员的格式访问静态成员,与非静态内部类创建外部类对象访问的方式不同。

局部内部类仅在该方法中有效,局部内部类不能在外部类的方法以外的地方使用,因此局部内部类也不能使用访问控制符和static修饰符修饰。

public class OutClass{
    public static void main(String[] args){
        
        class In{
            int a = 10;
        }
        //外部类以外访问静态内部类
        In i = new In();
        System.out.println(i.a);
    }
}

匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类或实现一个接口

匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象,因此不允许将匿名内部类定义成抽象类。

匿名内部类不能定义构造器,由于匿名内部类没有类名,无法定义构造器。

interface p{
    
}

public class Test{
    public void method(p s){
        
    }
    
    public static void main(String[] args){
        Test t = new Test();
        t.method(new p(){
            //匿名内部类
        });
    }
}

当通过实现接口来创建匿名内部类时,匿名内部类也不能显式创建构造器,因此匿名内部类只有一个隐式的无参数构造器,故new接口名后的括号不能传入参数值

如果通过继承父类来创建匿名内部类,匿名内部类将拥有和父类相似的构造器,拥有相同的形参列表。

 

面向对象:抽象类与接口、内部类、枚举类

原文:https://www.cnblogs.com/zaijie/p/11037742.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!