抽象类
抽象类是一种不能被实例化的类,其中至少包含一个抽象方法(即没有实现体的方法)。抽象类通常用于定义一组相关的类的共同特征,并强制其子类实现特定的方法。
抽象方法
将共性的方法抽取到父类之后,由于每个子类执行的内容不一样,所以在父类中不能确定具体的方法体,这样的方法就可以定义成为抽象方法
定义格式:
public abstract 返回值类型 方法名(参数列表);
public abstract void work();
抽象方法不能被static , final 修饰,抽象方法就是为了被重写的
匿名对象的方式调用抽象方法
前提已经写好了work的抽象方法和类的继承关系
public class Text { public static void working(Person p){ p.work(); } public static void main(String[] args) { Student student = new Student(); working(student); working(student); //匿名对象的方式调用方法 working(new Student()); working(new Student()); } }
普通的调用一个对象可以多次调用方法,匿名对象的方法调用每次调用都创建了对象
抽象类
如果一个类中有抽象方法,这个类就必须声明成抽象类
定义格式:
public abstract class 类名{}
public abstract class Person { public abstract void work(); }
注意:
1.抽象类不能实例化对象
2.抽象类中不一定有抽象方法,有抽象方法的类一定要设置成抽象类
3.抽象类可以有构造方法
4.抽象方法的子类要不重写父类的抽象方法,要不自身也是抽象类
那可能就有疑问了,既然抽象类不能实例化对象,那么要构造方法有什么用
通过向上转型的方式创建一个子类对象,通过父类的构造方法初始化子类继承的属性
接口
接口是一个完全抽象的类,用来规范类的行为,
比如有以上的继承关系,根据fish,student,teacher的共性来定义swim的行为,此时swim并不存在任何继承的关系,就可以把它定义为一个接口去被fish,student,teacher实现
接口的实现
1.接口使用关键字interface来定义
public interface 接口名{ }
2.接口不能实例化
3.接口和类是实现关系,通过关键字implements表示
public class 类名 implements 接口名{}
4.接口的子类要么重写接口中所有的抽象方法,要么是抽象类
5.接口和类之间可以单实现,也可以多实现,接口的出现,弥补了Java不能多继承的缺陷
接口中的成员变量默认是public static final修饰的,用static修饰调用方便,接口名.方法名调用,用》>final修饰,不可更改,所以也说明了接口中定义的是一种规范
接口中的方法是public abstract修饰的
所以说接口的实现类在重写接口的方法时只能用public修饰
接口中不能有代码块和构造方法
如果方法是被default和static修饰的可以有具体的实现
以下就是接口的实现例子:
实现多个接口
以下分别定义好了两个接口
public interface IRun { void run(); }
public interface ISwim { void swim(); }
Dog类继承Animal类之后再实现两个接口
public class Dog extends Animal implements ISwim,IRun{ public Dog() { super(); } public Dog(String name, int age) { super(name, age); } public void run(){ System.out.println(this.name + "在跑"); } public void swim() { System.out.println(this.name + "在游泳"); } }
测试类实现:
public class Text { public static void main(String[] args) { running(new Dog("大黄", 3)); swimming(new Dog("大黄", 3)); } public static void running(IRun iRun){ iRun.run(); } public static void swimming(ISwim iSwim){ iSwim.swim(); } }
接口与接口的关系
接口和接口之间是继承的关系,可以单继承也可以多继承
interface Ia{ void showA(); } interface Ib{ void showB(); } interface Ic extends Ia,Ib{ void showC(); } class D implements Ic{ public void showA() { } public void showB() { } public void showC() { } } public class Demo { }
Ic继承了Ia,Ib,同时类D实现了Ic接口,此时Ia,Ib,Ic的方法都需要重写,所以,接口间的继承相当于把多个接口结合在一起
内部类
内部类其实就是一个类里边再定义一个类,表示是外部类的一部分
访问特点:
内部类可以直接访问外部类的成员,包括私有的
外部类要访问内部类的成员,必须创建对象
public class Car { String carName; String carColor; //Car this可写可不写 public void show(Car this){ System.out.println(this.carName); //创建内部类的对象才能访问内部类成员变量 Engine e = new Engine(); System.out.println(e.engineName); } class Engine{ String engineName; int engineAge; public void show(){ //可以直接调用外部类成员变量 System.out.println(engineName); System.out.println(engineAge); } } }
成员内部类
成员内部类也就是写在成员位置的,属于外部类的成员,上面的代码就是一个成员内部类的例子,成员内部类可以被一些修饰符所修饰,例如private,默认,protexted,public,static等
在JDK16版本之前,成员内部类里面不能定义静态变量,JDK16开始才可以定义静态变量
获取内部类成员对象:
1.在外部类中编写方法,对外提供内部类对象
2.直接创建格式:
外部类名.内部类名 对象名 = 外部对象.内部对象;
遇到重名时的访问:
public class Outer { String name; private int a = 10; class Inner{ private int a = 20; public void show(){ int a = 30; System.out.println(Outer.this.a);//10 System.out.println(this.a);//20 System.out.println(a);//30 } } //外部类编写获取内部类的方法 public Inner getInnerInstance(){ return new Inner(); } }
静态内部类
静态内部类其实就是在成员内部类的基础上加上static修饰之后,就变为了静态内部类,静态内部类只能访问外部类中的静态变量和静态方法,如果要想访问非静态的需要创建对象
1.创建静态内部类对象的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
2.调用非静态方法的格式:先创建对象,用对象调用;
3.调用静态方法的格式:外部类名.内部类名.方法名
修改为以下代码
public class Souter { int a; static int b; static class Inner{ public void print(){ Souter s = new Souter(); System.out.println(s.a); System.out.println(b); } } }
方法的调用:
public class Souter { int a; static int b; static class Inner{ public void print(){ Souter s = new Souter(); System.out.println(s.a); System.out.println(b); } public static void show(){ System.out.println("静态内部类"); } } public static void main(String[] args) { //创建对象,对象名调用非静态方法 Souter.Inner inner = new Souter.Inner(); inner.print(); //类名调用静态方法 Souter.Inner.show(); } }
局部内部类
将内部类定义在方法里面就是局部内部类,类似于方法里面的局部变量
1.外界无法直接使用,需要在方法内部创建对象并使用
2.该类可以直接访问外部类的成员,也可以访问方法里的局部变量
public class Oouter { public void show(){ int a; class Inner{ String name; public void method1(){ System.out.println("局部内部类方法"); } public static void method2(){ System.out.println("局部内部类静态方法"); } } //创建对象访问局部内部类属性及方法 Inner inner = new Inner(); System.out.println(inner.name); inner.method1(); //类名访问静态方法 Inner.method2(); } }
匿名内部类
匿名内部类就是隐藏了名字的内部类
格式:
new 类名或接口名{
重写方法
};
大括号和前面的内容要么是实现关系,要么是继承关系,整体是一个类的子类对象或接口的实现类对象,大括号里面的是类
可以写在成员位置,也可以写在局部位置
如果不适用匿名内部类的方法,还需要再创建一个类去继承Animal,再去创建对象调用方法,效率不如匿名内部类高,这也就是匿名内部类的一个重要应用场景
下面是实现接口的例子: