一.匿名内部类
匿名内部类是局部内部类的一种特殊形式,是一个没有类名的局部内部类
我们想实现一个抽象类的方法需要怎么做呢?让我们看下面的过程
- 定义一个抽象类Person
public abstract class Person { public abstract void sleep(); }
-
定义一个Student类继承Person,并重写sleep方法
public class Student extends Person{
@Override
public void sleep() {
System.out.println("学生再睡");
}
}
- 创建Test类来写main方法进行测试
public class Test {
public static void main(String[] args) {
Person p = new Student();
p.sleep();
}
}
完成的功能平平无奇,但是确需要写三个类,我们发现想要调用Person中的抽象方法sleep方法,就必须创建一个子类,然后创建一个子类的实例对象然后再去调用方法。这可谓是把java面向对象的思想体现的淋漓尽致,万物皆对象嘛,这是java的优点,可是对于我们实现一个简单的功能,需要创建这么多对象,我们或多或少会觉得有些复杂了,那么有没有什么方法能够简化这一过程呢?
这就引出了我们这一部分的主角,匿名内部类。
我们使用匿名内部类如何实现上面的功能呢?
public static void main(String[] args) {
Person p = new Person() {
@Override
public void sleep() {
System.out.println("");
}
};
p.sleep();
}
这就是匿名内部类,我们对这个结构进行下分析
首先我们都知道抽象类是无法直接生成对象的,必须通过子类,但是通过代码我们能看到,这段代码在实现功能的过程中没有通过子类,而是通过
new Person{....};
来代替了new Student(),所以正常来说,这里应该是子类的位置,现在却通过父类实现了(我称其为以父之名)。
其次new Person{....};中的{....}实际是完成了Student子类中,对父类方法重写的过程,所以{....}被称为是类体
所以从理解角度来说 Person{....};是一个没有名字的子类,并且是在Tset内部的类,所以叫匿名内部类没毛病。
注:这里父类不一定要是抽象类,普通类和接口也可以,只要在匿名内部类中重写了父类方法即可
所以匿名内部类的使用前提是:必须继承—个父类或者实现—个接口
public static void main(String[] args) {
Person p = new Person() {
@Override
public void sleep() {
System.out.println("学生在睡觉");
}
};
Person p0 = new Person() {
@Override
public void sleep() {
System.out.println("工人在睡觉");
}
};
p0.sleep();
}
可以看到这样一来,我们就不需要关心,到底需要哪个对象来调用方法,只需要关注,方法体完成的事情本身就可以了,这样就有点像是把面向对象的编程思想,缩回了面向过程的
面向对象的方法固然好,因为我们的程序大部分是复杂的,大的东西,以后扩展,所以需要抽离出来会更加方便不可是总还是有一些事情,这些事情固然少可是总会有一些事情,就不会去变复杂去扩展,那我们就不需要去抽离,那就简单的面向过程就好了.
二、lambda表达式
函数式编程思想(面向过程),在数学中,函数是有输入量和输出量的一套计算方案,"就是那数据做操作",在面向对象的编程中强调必须用对象来做事情,函数式编程思想则尽量的忽略,对象的复杂语法,强调做什么,而不是以什么形式是去做,lambda就是函数是编程的具体体现
思考如何,启动一个线程,在控制台输出一句话,“多线程启动了”
方案1:
定义一个MyRunable的类,重写run方法
public class LambdaDemo{
public static void main(){
MyRunnable myRun
nable = new MyRunnable();
Thread t = new Tread(myRunnable);//线程类,必须实现了Runnable的接口的才是可以启动线程的
t.start;
}
}
class MyRunnable impl;ements Runnable{
public void run(){
System.out.println("多线程启动了")
}
}
方案二:
使用匿名内部类进行改进,省略了实现类,更注重于做事情
public static void main(){
Runnable run = new Runnable(){
public void run(){
System.out.println("多线程启动了") ;
}
} ;
Thread t = new Tread(run);//线程类,必须实现了Runnable的接口的才是可以启动线程的
t.start;
}
方案三:
lambda表达式 /*不需要表现是谁做的*/
Thread t = new Tread(( [run方法的参数] ])->{
System.out.println("多线程启动了")
});
t.start();
Thread t = new Tread(( )->{
System.out.println("多线程启动了")
});
t.start();
好这种写法看起来比匿名内部类还要简单,其实这是对匿名内部类的简化,初学者的话啊可以先写出匿名内部类形式,然后改写成lambda性质哦,
我们具体分析一下,Thread t = new Tread(...);这一部分中的...就是代替了实现Runnable类的对象
( )这个括号里面是public void run(),中的括号,是用来写方法参数的
->{
System.out.println("多线程启动了")
} 这一部分是方法体;
语法和要求
- 三要素:形式参数,箭头,代码块
- 格式:(形参)->代码块
- 形参要求:如果有多个形参,形参以逗号隔开,如果没有参数,括号不能省略
- ->由英文的中划线和大于号组成,这是固定写法表示执行
- 代码块:是我们具体要做的事,就是方法体和内容
- 使用前提:有一个接口,该接口只有一个抽象方法
示例1:无参无返回值
/*NoReturnNoParam 是一个接口
* 该接口只有一个方法method
*/
public interface NoReturnNoParam{
void method();
}
NoReturnNoParam noReturnNoParam = () -> {
System.out.println("NoReturnNoParam") ;
};
//调用方式
noReturnNoParam.method();
示例2:有参无返回值
public interface NoReturnOneParam{
void method(int a);
}
public interface NoReturnMultiParam{
void method(int a,int b);
}
NoReturnOneParam noReturnOneParam = (int a)->{
System.out.println(a+10);
};
NoReturnMultiParam noReturnMultiParam = (int a,int b)->{
System.out.println(a+b);
};
noReturnOneParam.method(10);
noReturnMultiParam.method(10,20);
示例3:有参有返回值
ReturnMultiParam returnMultiParam = (int a,int b) ->{
return a+b;
};
System.out.println(returnMultiParam.method(30,30));I