BD1 - Java 2-1 抽象类 接口 内部类

2017-07-29  本文已影响83人  hongXkeX

We believe that writing is about content, about what you want to say – not about fancy formatting.
我们坚信写作写的是内容,所思所想,而不是花样格式。
— Ulysses

Java第5天上午

上午主要讲了抽象类和接口

抽象类:

问题提出:


1

利用多态性实现不合理:


利用多态性实现不合理

抽象的概念定义为抽象类/抽象方法更加合理
注意上图中抽象方法的形式 没有{ }!

抽象类的特点:

抽象类的特点

编程练习:编写程序,创建两个几何对象,一个圆和一个正方形,调用方法检查两个对象是否有相同的面积,

// Shape.java:
public abstract class Shape {
    /**
     * 抽象获取面积的方法 
     * @return 形状面积
     */
    public abstract double getArea();
    /**
     * 比较两个形状的大小
     * @param p 另一个形状的实例
     * @return 如果当前形状较大则返回true
     */
    public boolean compareArea(Shape p){
        return this.getArea()>p.getArea();
    }
}

// Circle.java: 
public class Circle extends Shape{
    private double radius;
    public Circle(double radius) {
        this.radius = radius;
    }
    @Override
    public double getArea() {
        return Math.PI*radius*radius;
    }
}

// Square.java:
public class Square extends Shape{
    private double length;
    public Square(double length) {
        this.length = length;
    }
    @Override
    public double getArea() {
        return length*length;
    }
}

// Test.java:
public class Test {
    public static void main(String[] args) {
        Shape s1 = new Square(2);
        Shape s2 = new Circle(2);       
        System.out.println(s1.getArea());
        System.out.println(s2.getArea());
        System.out.println(s1.compareArea(s2));
    }
}

// 结果:
4.0
12.566370614359172
false

接口:

接口更抽象,仅声明了方法:


接口仅声明了方法

implements关键字实现接口:

implements实现接口 Paste_Image.png

接口和抽象类区别:

接口与类 接口和抽象类 接口和抽象类 接口和抽象类2 接口和抽象类3 接口和抽象类区别 接口和抽象类区别
Abstract class Interface
实例化 不能 不能
一种继承关系,一个类只能使用一次继承关系。可以通过继承多个接口实现多重继承 一个类可以实现多个interface
数据成员 可有自己的 静态的不能被修改即必须是static final,一般不在此定义
方法 可以私有的,非abstract方法,必须实现 不可有私有的,默认是public,abstract 类型
变量 可有私有的,默认是friendly 型,其值可以在子类中重新定义,也可以重新赋值 不可有私有的,默认是public static final 型,且必须给其初值,实现类中不能重新定义,不能改变其值。
设计理念 表示的是“is-a”关系 表示的是“like-a”关系
实现 需要继承,要用extends 要用implements

一个类可以实现自多个接口:

类可以实现多个接口

类需要替代这两个接口所定义的所有方法

重点说明: (用接口实现多重继承)

Java不支持多重继承原因 Java不支持多重继承原因

拓展示例:


示例 总结 抽象类可以用作数据类型

对比补充:


普通方法和抽象方法 普通类和抽象类 抽象类的优势

抽象类——模板设计模式:


模板设计模式

抽象类小练习:


练习 理解接口 实现多接口

final:

final

老师上午给的2个PPT请点我查看下载

拓展阅读:

1 - Java 接口的作用和好处
2 - Java 接口(interface)的用途和好处
3 - Java 抽象类与接口的区别
4 - 详细解析Java中抽象类和接口的区别

拓展:

了解Math类:
The class contains methods for performing basic numeric operations such as the elementary exponential, logarithm, square root, and trigonometric functions

里面包含了很多常用常量(如e和PI)和数学函数(如sin()、con()等):


Math.class

下午讲了内部类:

Java内部类

在Java中,可以将一个类定义在另一个类里面或者一个方法(类成员函数)里面,这样的类称为内部类。广泛意义上的内部类一般来说包括四种:

成员内部类:

class Circle {
    double radius = 0;
     
    public Circle(double radius) {
        this.radius = radius;
    }
     
    class Draw {     // 成员内部类
        public void drawSahpe() {
            System.out.println("drawshape");
        }
    }
}

看起来,类Draw像是类Circle的一个成员,Circle称为外部类。成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)

class Circle {
    private double radius = 0;
    public static int count =1;
    public Circle(double radius) {
        this.radius = radius;
    }
     
    class Draw {     //内部类
        public void drawSahpe() {
            System.out.println(radius);  //外部类的private成员
            System.out.println(count);   //外部类的静态成员
        }
    }
}

要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:

外部类.this.成员变量
外部类.this.成员方法

成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:

class Circle {
    private double radius = 0;
 
    public Circle(double radius) {
        this.radius = radius;
        getDrawInstance().drawSahpe();   //必须先创建成员内部类的对象,再进行访问
    }
     
    private Draw getDrawInstance() {
        return new Draw();
    }
     
    class Draw {     //内部类
        public void drawSahpe() {
            System.out.println(radius);  //外部类的private成员
        }
    }
}

成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。创建成员内部类对象的一般方式如下:

public class Test {
    public static void main(String[] args)  {
        //第一种方式:
        Outter outter = new Outter();
        Outter.Inner inner = outter.new Inner();  //必须通过Outter对象来创建
         
        //第二种方式:
        Outter.Inner inner1 = outter.getInnerInstance();
    }
}
 
class Outter {
    private Inner inner = null;
    public Outter() {
         
    }
     
    public Inner getInnerInstance() {
        if(inner == null)
            inner = new Inner();
        return inner;
    }
      
    class Inner {
        public Inner() {
             
        }
    }
}

内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。比如上面的例子,如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。

局部内部类:
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

class People{
    public People() {
         
    }
}
 
class Man{
    public Man(){
         
    }
     
    public People getWoman(){
        class Woman extends People{   //局部内部类
            int age =0;
        }
        return new Woman();
    }
}

注意,局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。

匿名内部类:
匿名内部类应该是平时我们编写代码时用得最多的,在编写事件监听的代码时使用匿名内部类不但方便,而且使代码更加容易维护。

下面这段代码是一段Android事件监听代码:

scan_bt.setOnClickListener(new OnClickListener() {         
    @Override
    public void onClick(View v) {
    
    }
});

这段代码为按钮设置监听器,这段代码中的:

new OnClickListener() {
    public void onClick(View v) {
                 
    }
}

上面就是匿名内部类的使用。代码中需要给按钮设置监听器对象,使用匿名内部类能够在实现父类或者接口中的方法情况下同时产生一个相应的对象,但是前提是这个父类或者接口必须先存在才能这样使用。

当然像下面这种写法也是可以的,跟上面使用匿名内部类达到效果相同:

private void setListener()
{
    scan_bt.setOnClickListener(new Listener1());       
    history_bt.setOnClickListener(new Listener2());
}
 
class Listener1 implements View.OnClickListener{
    @Override
    public void onClick(View v) {
             
    }
}
class Listener2 implements View.OnClickListener{
    @Override
    public void onClick(View v) {
             
    }
}

这种写法虽然能达到一样的效果,但是既冗长又难以维护,所以一般使用匿名内部类的方法来编写事件监听代码。同样的,匿名内部类也是不能有访问修饰符和static修饰符的。

匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outter$1.class。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。

静态内部类:
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。

public class Test {
    public static void main(String[] args)  {
        Outter.Inner inner = new Outter.Inner();
    }
}
 
class Outter {
    public Outter() {
         
    }
     
    static class Inner {
        public Inner() {
             
        }
    }
}

内部类的使用场景和好处:
为什么在Java中需要内部类?
总结一下主要有以下四点:

认为第一点是最重要的原因之一,内部类的存在使得Java的多继承机制变得更加完善

补充:
关于成员内部类的继承问题。一般来说,内部类是很少用来作为继承用的。但是当用来继承的话,要注意两点:

class WithInner {
    class Inner{
         
    }
}
class InheritInner extends WithInner.Inner {
      
    // InheritInner() 是不能通过编译的,一定要加上形参
    InheritInner(WithInner wi) {
        wi.super(); //必须有这句调用
    }
  
    public static void main(String[] args) {
        WithInner wi = new WithInner();
        InheritInner obj = new InheritInner(wi);
    }
}

老师下午给的word请点我查看下载


每日一练:

课堂作业:
没留 暂无

课外练习:
课外作业点我查看


拓展阅读:

1 - Java内部类的使用小结
2 - java提高篇(八)----详解内部类
3 - java中的内部类总结

后记
世界上所有的追求都是因为热爱
一枚爱编码 爱生活 爱分享的IT信徒
— hongXkeX

上一篇下一篇

猜你喜欢

热点阅读