抽象类和接口及Lambda

内部类

匿名内部类为不怕是从来不名字的里类,匿名内部类就是再写父类或接口的章程。

刚刚为无名字,所以匿名内部类只能采用相同次等,它一般用来简化代码编写

然而下匿名内部类还出只前提条件:必须连续一个华而不实类还是实体类还是接口

实例1:不应用匿名内部类来实现抽象方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
abstract class Person {
    public abstract void eat();
}
 
class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

运作结果:eat something

足见到,我们就此Child继承了Person类,然后实现了Child的一个实例,将该长进转型也Person类的援

而,如果这里的Child类只下同一蹩脚,那么以那个编写为独立的一个好像岂不是颇辛苦?

其一时便引入了匿名内部类

 

实例2:匿名内部类的中心落实

1
2
3
4
5
6
7
8
9
10
11
12
13
14
abstract class Person {
    public abstract void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

运行结果:eat something

好望,我们一直将抽象类Person中之计以大括哀号中落实了

这么就是足以大概一个类似的修

而,匿名内部类还能够用于接口及

 

实例3:在接口及以匿名内部类

interface Person {
    public void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

运作结果:eat something

 

是因为方的例证可以看出,只要一个类是空泛的可能一个接口,那么其子类中的法都得采用匿名内部类来实现

太常用之情就是是当多线程的贯彻达标,因为要是落实多线程必须继承Thread类或是继承Runnable接口

 

实例4:Thread类的匿名内部类实现

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        t.start();
    }
}

运行结果:1 2 3 4 5

 

实例5:Runnable接口的匿名内部类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Demo {
    public static void main(String[] args) {
        Runnable r = new Runnable() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }
}

运转结果:1 2 3 4 5

 

干什么引入抽象类?

空泛类 : 几哪里图形class Figure

子类: 矩形class Rectangle 圆class Circle三角形class Triangle 等…   属性:
曲边 ,直边, 几条边, 求面积, 求周长…

假若没抽象类,父类提取出来的共性必须是唯一的,实现之,稳定之,那么要面积,求周长,都非克领取,当一个主意的力量是处理几乎哪里图形,参数是Figure
f .当接收一个图时,求其周长还要事先把 f
向下转型,很是麻烦.但是要引入抽象类,可以把要周长的公式提取出来,但是不用实现,当然为束手无策实现.这样虽不要于下转型了.增加了灵活性,而且子类继承了抽象类,必须管抽象类的富有抽象方法要备实现,才能够new实例,这样抽象类带来了另外一个利益:模板,规定子类必须要怎么!

泛泛类标准

(1)抽象类用abstract修饰,抽象类不克new出实体

(2)抽象类提取出的共性,能兑现之直接实现,不可知落实之之所以abstract修饰,不必实现,由子类继承重写

(3)抽象类应该尽量提取最多之共性,不用于乎能不能实现.

(4)抽象类不克new出实体,就是之所以来都要被连续的,继承者必须再次写那总体之悬空方法,才能够new出实体,否则,继承者也是个泛类.

(5)abstract修饰的近乎为持续才起含义,abstract修饰的方式给再度写才会new出实体,而final修饰的类非可知吃持续,方法不能够于重复写,所以abstract和final不克同时使用.

(6)private修饰的章程子类无法接触,所以private和abstract也不通用.

(7)抽象类为发出构造器,但是这构造器并无是以new出目标,而是于后任的构造器调用的.

 

抽象方法和普通方法 形式上的区别:
public abstruct void abstructFun();
public          void fun() {}

 接口

/*接口的权能是public或friendly,能连续一个或多只接口,不可知随着承类,不含构造器,不含有初始化块*/

interface JieKou extends 接口1,接口2… {

    /* 接口的拥有成员都是public
,就比如C语言的const修饰的变量,不再改变,就是”模板”
*/

    public static final int VAR = 20;

    /*static 省空中,final
是正统就是绝不还修改,必须定义时直初始化*/

    //int VAR = 20;

    /*寻常方法必须是虚幻的 public
abstruct,不用实现 */

    void f();

    /*类措施 public static
,必须实现 */

    static void g() {

        System.out.println(“我是类似方式”);

    }

    /*默认方法为要实现 public
*/

    default void print(String… msgs) {

        for(String msg : msgs) {

            System,out.println(msg);

        }

    }

    /*另外成员:内部类,内部接口,枚举类*/

}

 

接口不克new出实体,接口可以视作援变量,指向类new出的实体.

<1>定义引用变量,也得拓展强制类型转换

<2>调用接口的常量

<3>被另外类似实现

一个近似可以多延续很多接口,但是只能连续一个类.

class extends 类 implements
接口1,接口2…
{

   

}

一个类似继承了接口,必须实现接口中具备的虚幻方法,不然还是只能当抽象类用.

继承接口的类重写接口的悬空方法时,权限C语言只能是public,因为子类重写父类时,只能用相同或又甚之权限.

抽象类和接口的界别

C语言 1

 

接口的利用:

有方法要就一个作为,但是这行为临时无晓是呀,只有执行措施时,才知道.比如,一个道时处理数组,遍历数组的时,对数组元素执行什么操作暂时无确定,需要现规定作为,解决方法就是是概念一个接口.

 1 import java.util.*;
 2 public class TestJava {
 3     public static void main(String[] args) {
 4         int[] a = new int[10];
 5         for(int i = 0;i < a.length;++i)
 6             a[i] = i;
 7             
 8         for(int i = 0;i < a.length;++i) 
 9             System.out.print(a[i]);
10         
11         TestFun tf = new TestFun();
12         tf.f(a,new Set0());
13         
14         for(int i = 0;i < a.length;++i)
15             System.out.print(a[i]);
16         
17         tf.f(a,new Set1());
18         for(int i = 0;i < a.length;++i)
19             System.out.print(a[i]);
20     }
21 }
22 
23 interface JieKou {
24     void set(int[] a);
25 }
26 
27 class Set0 implements JieKou {
28     public void set(int[] a) {
29         for(int i = 0;i < a.length;++i) {
30             a[i] = 0;
31         }
32     }
33 }
34 
35 class Set1 implements JieKou {
36     public void set(int[] a) {
37         for(int i = 0;i < a.length;++i) {
38             a[i] = 1;
39         }
40     }
41 }
42 
43 class TestFun {
44     void f(int[] a,JieKou jk) {
45         jk.set(a);
46     }
47 }

 Lambda表达式

怎么动态的传入一段落代码,作为具体的处理作为?

(1)
动态处理代码封装成一个接口a的泛方法.定义一个持续接口的类a,重写抽象方法.传入类,在行使动态处理代码的计被经过类似名.方法以代码.

(2)直接把接口的援作为艺术参数,void f(int [ ] a, new JieKou {
重写抽象方法} );  匿名内部类

(3)使用Lambda表达式

Lambda表达式支持以代码块当艺术参数,Lmabda表达式可以重简短的开创函数式接口的一个实体.

函数式接口:
可以有多只默认方法,类措施,只来一个空洞方法的接口叫函数式接口.

利用匿名内部类.

 1 import java.util.*;
 2 public class TestJava {
 3     public static void main(String[] args) {
 4         int[] a = new int[10];
 5         
 6       TestFun tf = new TestFun();
 7       tf.f(a,new JieKou() {
 8           public void set(int[] a) {
 9               for(int i = 0;i < a.length;++i)
10                 a[i] = 2;
11           }
12         });
13      for(int i = 0;i < a.length;++i)
14             System.out.print(a[i]);
15     }
16 }
17 
18 interface JieKou {
19     void set(int[] a);
20 }
21 
22 class TestFun {
23     void f(int[] a,JieKou jk) {
24         jk.set(a);
25     }
26 }

使用Lambda表达式

 Lambda表达式:只有一个展示参时,可以大概圆括号,只发同等长条告句时,可以简单{ },
若方法体是 c = a + b; return c; 可以简写成 c = a + b; 它见面自行回到回.

Lambda与匿名内部类的相同点和区别

 1 interface Displayable {
 2     void Display(int i);
 3     default void f() {
 4         System.out.println("我是接口的默认方法");
 5     }
 6 }
 7 
 8 public class TestLambda {
 9     private String name = new String("哈哈哈");
10     void test() {
11         Displayable dis = i->{
12         System.out.println("我是接口的抽象方法,我要显示"+i);
13         System.out.println("我要访问name,name是:"+name);
14       };
15       dis.f();
16       dis.Display(3);
17     }
18     
19     public static void main(String[] args) {
20         TestLambda tl = new TestLambda();
21         tl.test();
22     }
23 }

 1 问题: 方法A需要处理一个数组,怎样处理临时起意,不确定.
 2 (1)把处理方法封装成接口
 3 interface JieKou {
 4     处理方法process;
 5 }
 6 (2)写方法A
 7 A(数组引用,JieKou引用)
 8 (3)使用方法A
 9      1.匿名内部类
10      A(数组引用,接口引用() {重写处理方法process});
11      2.Lambda表达式
12      A(数组引用,(process的参数列表)->{方法体})
13 两种方法都避免了为了一个动态处理代码块创建一个类,优化了项目.
14 注意:Lambda表达式返回一个引用.接口是函数式接口时,才能用Lambda表达式简写.
15 Lambda表达式就是为函数式接口创建实体的.
16 Runnable是个函数式接口,只含有一个抽象方法
17 Runnable r = ()->{System.out.println("Lambda表达式实现函数式接口的实体")};
18 Object r = ()->{System.out.println("Lambda表达式实现函数式接口的实体")};//error
19 因为Object不是一个函数式接口,用函数式接口强制类型转换后可以用Object引用指向.
20 Object r = (Runnable)()->{System.out.println("Lambda表达式实现函数式接口的实体")};//OK
21 将Lambda表达式赋值给一个函数式接口的引用变量
22 将Lambda表达式作为函数式接口的形参
23 使用函数式接口对Lamable表达式进行强制类型转换.

 匿名内部类是接口就可知创实体,但是Lambda表达式只能为函数式接口创建实体.

匿名内部类还足以呢抽象类,实体类创建实体.

匿名内部类在实现抽象方法时得以调用接口的默认方法,但是Lambda表达式不可以.