抽象类
抽象方法和抽象类的定义格式
- 抽象方法定义:将共性的行为抽取到父类之后,由于每一个子类执行的内容是不一样的,所以在父类中不能确定具体的方法体,该方法就可以定义为抽象方法
- 抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类
- 抽象方法定义格式:
pubic abstract int maxValue(int[] arr);
4. 抽象类的定义格式:
public abstract class AddTwo{}
5. 抽象类和抽象方法的注意事项
抽象类不能被实例化
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
可以有构造方法:作用 创建子类对象时,给属性进行赋值
抽象类的子类:
要么重写抽象类中的所有抽象方法
要么是抽象类
接口
为什么有接口?
接口就是一种规则,对行为的抽象
如何定义一个接口?
1. 定义:接口用关键字interface来定义
public interface add{}
2. 接口不能实例化
3. 接口和类之间是实现关系,通过implements关键字表示
public class Student implements add{}
4. 接口的子类(实现类)
要么重写接口中的所有抽象方法
要么是抽象类
注意:1)接口和类的实现关系,可以是单实现,也可以是多实现
public class Student implements add,maxValue{}
2)实现类还可以再继承一个类的同时实现多个接口
5. 完整代码
package interfaceTest;
public interface Swim {
abstract void swim();
}
接口中成员的特点
- 成员变量
只能是常量
默认修饰符:public static final
2. 构造方法
没有
3. 成员方法
只能是抽象方法
默认修饰符:public abstract
JDK7以前:接口中只能定义抽象方法
JDK8的新特性:接口中可以定义有方法体的方法
JDK9的新特性:接口中可以定义私有方法
接口和类之间的关系
类和类之间的关系
继承关系,只能单继承,不能多继承,但是可以多层继承
类和接口的关系
实现关系,可以单实现,也可以多实现,还可以再继承一个类的同时实现多个接口
若接口中有重名的方法,则重写一次就好
例如:Inter1:
public interface Inter1 {
void method1();
void method2();
void method3();
}
Inter2:
public interface Inter2 {
void method1();
void method2();
void method6();
}
实现类:
package interfacedemo3;
public class InterImpl implements Inter1,Inter2{
@Override
public void method1() {
System.out.println("method1");
}
@Override
public void method2() {
System.out.println("method2");
}
@Override
public void method6() {
System.out.println("method6");
}
@Override
public void method3() {
System.out.println("method3");
}
}
接口和接口的关系
继承关系,可以单继承,也可以多继承,但是如果实现类实现了子接口,则需要重写接口所有方法
例如:Inter1:
public interface Inter1 {
void method1();
}
Inter2:
public interface Inter2 {
void method2();
}
Inter3:
public interface Inter3 extends Inter1,Inter2{
void method3();
}
实现类:
public class InterImpl implements Inter3{
@Override
public void method3() {
}
@Override
public void method1() {
}
@Override
public void method2() {
}
}
JDK8开始接口中新增的方法
JDK8以后接口中新增的方法
- 允许接口中定义默认方法,需要使用关键字default修饰 作用:解决接口升级问题
- 接口中默认方法定义格式:
格式:public default 返回值类型 方法名(参数列表){}
范例:public default void show(){}
public interface Inter {
void method();
public default void show(){
System.out.println("default method");
}
}
3. 接口中默认方法的注意事项:
默认方法不是抽象方法,所有不强制被重写。但是如果被重写,重写的时候去掉default关键字;
public可以省略,default不能省略;
如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写;
4. 允许在接口中定义静态方法,需要用static修饰
5. 接口中静态方法的定义格式:
格式:public static 返回值类型 方法名(参数列表){}
范例:public static void show(){}
public interface Inter {
void method();
static void show(){
System.out.println("Hello World");
}
}
6. 接口中静态方法的注意事项:
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
public可以省略,static不能省略
总结:JDK8的新特性:接口中可以定义有方法体的方法(默认,静态)
JDK9的新特性:接口中可以定义私有方法
接口中私有方法的定义格式:
格式1:private 返回值类型 方法名(参数列表){}
范例1:private void show(){}
public interface Inter {
public default void show1(){
System.out.println("show start");
}
public default void show2(){
System.out.println("show end");
}
private void show3(){
System.out.println("hhh 100 code");
}
}
格式2:private static 返回值类型 方法名(参数列表){}
范例2:private static void method(){}
私有方法分两种:普通的私有方法和静态的私有方法
接口的应用
接口代表规则,是行为的抽象。想要让哪个类拥有一个行为,就让这个类实现对应的接口就可以
当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态
适配器设计模式
设计模式(Design pattern):为了可重用代码,让代码更容易被他人理解,保证代码可靠性,程序的重用性
适配器设计模式:解决接口与接口实现类之间的矛盾问题
相当于在接口和实现类之间添加了一个类,该类空实现接口,然后让实现类继承这个类,重写里面的方法即可。
书写步骤:
- 编写中间类XXXAdapter,实现对应的接口
- 对接口中的抽象方法进行空实现
- 让真正的实现类继承中间类,并重写需要用的方法
- 为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰
内部类
类的五大成员:
属性,方法,构造方法,代码块,内部类
定义
在一个类里面,再定义一个类
为啥有内部类
内部类表示的事物是外部类的一部分
内部类单独出现没有任何意义
内部类的访问特点
内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建内部类的对象
内部类的分类
成员内部类
静态内部类
局部内部类
匿名内部类:掌握
成员内部类
定义:写在成员位置的,属于外部类的成员
书写格式:
public class Car {
private String carName;
private String carColor;
int carAge;
public void show(){
System.out.println("Car Name: " + carName);
Engine engine = new Engine();
engine.enginAge = 10;
System.out.println("Car age: " + engine.enginAge);
}
class Engine{
private String carEngine;
int enginAge;
public void show(){
System.out.println("Car Name: " + carName);
System.out.println("engine age: " + enginAge);
}
}
}
成员内部类可以被一些修饰符所修饰,比如:private,默认(在本包中使用),protected(在其他类的子包中),public,static等
在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量
获取成员内部类对象
方式一:
在外部类中编写方法,对外提供内部类的对象
public class Outer {
String name;
class Inner {
}
public Inner getInner() {
return new Inner();
}
}
public class Test {
public static void main(String[] args) {
Outer o = new Outer();
o.getInner();
}
}
方式二:
直接创建格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;(适用于private修饰的成员内部类)
public class Outer {
String name;
class Inner {
}
}
public class Test {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
}
}
当外部类成员变量和内部类成员变量重名时,在内部类如何访问?
public class Outer {
private int x = 10;
class Inner {
private int x = 20;
public void show(){
int x = 30;
System.out.println(x);
System.out.println(this.x);
System.out.println(Outer.this.x);
}
}
}
静态内部类
静态内部类指的是在内部类的前面加上static关键字,静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象
创建静态内部类对象的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名
调用非静态方法格式:先创建对象,用对象调用
调用静态方法格式:外部类名.内部类名.方法名
局部内部类
1. 将内部类定义在方法里面就是局部内部类,类似于方法里面的局部变量
2. 外界是无法直接使用,需要在方法内部创建对象并使用
3. 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
package linnerdemo5;
import org.w3c.dom.ls.LSOutput;
public class Outer {
int b = 10;
public void show(){
int a = 20;
class Inner{
String name;
int age;
public void show1(){
System.out.println("show1");
System.out.println(b);
System.out.println(a);
}
public static void show2(){
System.out.println("static show2");
}
}
Inner inner = new Inner();
inner.show1();
inner.age = 10;
inner.name = "lazyGirl";
inner.show2();
Inner.show2();
}
}
匿名内部类
定义:匿名内部类本质上就是隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置 实现或继承 方法的重写 对象创建
格式: new 类名或者接口名(){
重写方法;
};
重写接口
public class Test {
public static void main(String[] args) {
new Swim(){
@Override
public void swim() {
System.out.println("rewrite swim");
}
};
}
}
重写类
new Animal(){
@Override
public void eat() {
System.out.println("rewrite eat");
}
};
文件夹显示:
反编译看class文件内容:
使用场景:当方法的参数是接口或者类时,以接口为例,可以传递这个接口的实现类对象,若实现类只要使用一次,就可以用匿名内部类简化代码