一.抽象类
抽象方法:
-
public abstract 返回值类型 方法名(参数列表);
将共性的行为(方法)抽取到父类之后
,发现该方法的实现逻辑无法在父类中给出具体明确
,该方法就可以定义为抽象方法
抽象类:
-
public abstract class 类名{}
如果一个类中存在抽象方法
,那么该类就必须声明为抽象类
抽象类特点
- 抽象类不能实例化
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 可以有构造方法
-抽象类的子类,要么重写抽象类中的所有抽象方法,要么还是抽象类
动物类
public abstract class Animal {
public void drink(){
System.out.println("喝水");
}
public Animal(){
}
public abstract void eat();
}
猫类
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
狗类
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
测试类
public static void main(String[] args) {
Dog d = new Dog();
d.eat();
d.drink();
Cat c = new Cat();
c.eat();
c.drink();
//Animal a = new Animal();
//a.eat();
}
- ``
狗吃肉
喝水
猫吃鱼
喝水
二.接口
当一个类中的所有方法都是抽象方法的时候,我们就可以将其定义为接口
1.声明
-
接口用关键字interface来定义
public interface 接口名 {}
-
接口和类之间是实现关系,通过implements关键字表示
public class 类名 implements 接口名 {}
public class 类名 implements 接口名1 , 接口名2 {}
2.特点
-
接口不能实例化
-
接口的子类(实现类),要么重写接口中的所有抽象方法,要么是抽象类
-
成员变量
只能是常量�默认修饰符:public static final -
没有构造方法
-
成员方法
只能是抽象方法, 默认修饰符:public abstract
JDK8版本后
- 允许在接口中定义非抽象方法,但是需要使用关键字 default 修饰,这些方法就是默认方法
作用:解决接口升级的问题
- 接口中允许定义static静态方法
实例
接口
public interface Inter {
public static final int NUM = 10;
public abstract void show();
}
实现类
class InterImpl implements Inter{
public void method(){
// NUM = 20;
System.out.println(NUM);
}
public void show(){
}
}
测试类
public class TestInterface {
/*
成员变量: 只能是常量 系统会默认加入三个关键字
public static final
构造方法: 没有
成员方法: 只能是抽象方法, 系统会默认加入两个关键字
public abstract
*/
public static void main(String[] args) {
System.out.println(Inter.NUM);
}
}
类和接口的关系
- 类和类的关系
继承关系,只能单继承,但是可以多层继承 - 类和接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口 - 接口和接口的关系
继承关系,可以单继承,也可以多继承
接口与父类冲突
- 如果直接父类, 和接口中出现了相同的方法声明, 但是代码逻辑不一样,优先使用直接父类的代码逻辑.
三.内部类
在一个类中定义一个类。举例:在一个A类的内部定义一个B类, B类就被称为内部类
public class Outer {
public class Inner {
}
}
内部类的访问特点
- 内部类可以直接访问外部类的成员,包括私有对象
- 外部类要访问内部类的成员,必须创建对象
成员内部类
将一个类,设计为内部类的目的,大多数都是不想让外界去访问,所以内部类的定义应该私有化,私有化之后,再提供一个可以让外界调用的方法,方法内部创建内部类对象并调用。
class Outer {
private int num = 10;
private class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
Inner i = new Inner();
i.show();
}
}
public class InnerDemo {
public static void main(String[] args) {
//Outer.Inner oi = new Outer().new Inner();
//oi.show();
Outer o = new Outer();
o.method();
}
}
匿名内部类
是一个继承了该类或者实现了该接口的子类匿名对象
interface Inter{
void method();
}
class Test{
public static void main(String[] args){
new Inter(){
@Override
public void method(){
System.out.println("我是匿名内部类");
}
}.method(); // 直接调用方法
}
}
匿名内部类在开发中的使用
当发现某个方法需要,接口或抽象类的子类对象,我们就可以传递一个匿名内部类过去,来简化传统的代码
/*
游泳接口
*/
interface Swimming {
void swim();
}
public class TestSwimming {
public static void main(String[] args) {
goSwimming(new Swimming() {
@Override
public void swim() {
System.out.println("铁汁, 我们去游泳吧");
}
});
}
/**
* 使用接口的方法
*/
public static void goSwimming(Swimming swimming){
/*
Swimming swim = new Swimming() {
@Override
public void swim() {
System.out.println("铁汁, 我们去游泳吧");
}
}
*/
swimming.swim();
}
}
四:Lambda表达式
1.格式 :
(形式参数) -> {代码块}
-
三要素 :
形式参数,箭头,代码块
-
形式参数
:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可 -
->
:由英文中画线和大于符号组成,固定写法。代表指向动作 -
代码块
:是我们具体要做的事情,也就是以前我们写的方法体内容
2.使用前提
- 有一个接口
- 接口中有且仅有一个抽象方法
实例1:有参有返回值
interface Flyable {
String fly(String s);
}
class FlyableDemo {
public static void main(String[] args) {
//在主方法中调用useFlyable方法
//匿名内部类
useFlyable(new Flyable() {
@Override
public String fly(String s) {
s = s + "晴空万里";
System.out.println(s);
return s ;
}
});
System.out.println("--------");
//Lambda
useFlyable((String s) -> {
s = "Lambda:" + s + "晴空万里";
System.out.println(s);
return s;
});
}
private static void useFlyable(Flyable f) {
f.fly("Override:风和日丽,");
}
}
实例2:表达式的省略模式
interface Addable {
int add(int x, int y);
}
interface Flyable {
void fly(String s);
}
public class LambdaDemo {
public static void main(String[] args) {
// 1.参数的类型可以省略
// useAddable((int x,int y) -> {
// return x + y;
// });
useAddable((x, y) -> {
return x + y;
});
// useFlyable((String s) -> {
// System.out.println(s);
// });
//2.如果参数有且仅有一个,那么小括号可以省略
// useFlyable(s -> {
// System.out.println(s);
// });
//3.如果代码块的语句只有一条,可以省略大括号和分号
useFlyable(s -> System.out.println(s));
//4.如果代码块的语句只有一条,可以省略大括号和分号,如果有return,return也要省略掉
useAddable((x, y) -> x + y);
}
//接口的实现
private static void useFlyable(Flyable f) {
f.fly("风和日丽,晴空万里");
}
private static void useAddable(Addable a) {
int sum = a.add(10, 20);
System.out.println(sum);
}
}
3.Lambda表达式和匿名内部类的区别
-
所需类型不同
匿名内部类
:可以是接口,也可以是抽象类,还可以是具体类
Lambda表达式
:只能是接口 -
使用限制不同
1
: 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
2
: 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式 -
实现原理不同
匿名内部类
:编译之后,产生一个单独的.class字节码文件
Lambda表达式
:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成
网友评论