一、抽象类
1、abstract修饰类,即抽象类
- 此类不能实例化;
- 此类有构造器,子类实例化过程中会调用该父类的构造器;
2、abstract修饰方法,即抽象方法
- 只有方法的声明,没有方法体;
//抽象方法:eat()方法
public abstract void eat();
- 包含抽象方法的类一定是抽象类(此方法不能被调,即该类不能不能实例化);
- 若子类重写了父类(父类为抽象类)中所有抽象方法后,才可以实例化,若没有重写,则子类也是一个抽象类;
3、利用抽象父类创建匿名子类或创建匿名子类的匿名对象
public class AbstractTest {
public static void main(String[] args) {
//1、利用抽象父类来创建匿名子类 但是有对象名 即f(并重写抽象父类中的抽象方法)
Father f = new Father() {
@Override
public void eat() {
System.out.println("匿名子类重写的方法1");
}
@Override
public void play() {
System.out.println("匿名子类重写的方法2");
}
};
//2、匿名子类的匿名对象 (利用抽象父类声明匿名子类 且没有对象名)
method(new Father() {
@Override
public void eat() {
System.out.println("");
}
@Override
public void play() {
}
});
method(f);
}
//声明static方法 即在主类中可以直接调用 不用声明对象来调用
public static void method(Father f){
f.eat();
f.play();
}
}
//抽象类(不能被实例化)
abstract class Father{
String name;
int age;
public Father(){
}
public Father(String name,int age){
this.name = name;
this.age = age;
}
//抽象方法
public abstract void eat();
public abstract void play();
}
class son extends Father{
//如果不是抽象子类则必须重写父类中的抽象方法
@Override
public void eat(){
System.out.println("overwrite method : eat()");
}
@Override
public void play() {
System.out.println("overwrite method : play()");
}
}
4、模板方法设计模式
public class TemplateTest {
public static void main(String[] args) {
//多态创建实例
Template t = new subTempalte();
//调用子类继承的spendTime()方法
t.spendTime();
}
}
abstract class Template{
public void spendTime(){
long start = System.currentTimeMillis();
code();
long end = System.currentTimeMillis();
code();
System.out.println("花费的时间为: " + (end-start));
}
public abstract void code();
}
class subTempalte extends Template{
@Override
//计算100以内质数的时间
public void code() {
for (int i = 2; i <= 100; i++){
boolean isFlag = true;
for (int j = 2; j <= Math.sqrt(i); j++){
if (i % j == 0){
isFlag = false;
break;
}
}
if (isFlag){
System.out.println(i);
}
}
}
}
二、接口
1、接口用interface声明
2、接口与类是并列的
3、JDK8之前的使用:可以定义全局常量和抽象方法
- 全局常量: 使用public static final定义,在接口中可以省略不写;
- 抽象方法: 使用public abstract定义,可以省略不写;
4、接口中不能定义构造器,则接口不可以实例化;
5、接口通过让类实现的方式来使用
- 如果实现类覆盖了接口中所有的抽象方法,则该实现类可以实例化;
- 如果实现类没有覆盖了接口中所有的抽象方法,则该实现类还是一个抽象类,即不能实例化;
6、Java可以实现多个接口(多重接口)---类是单继承的(不能多重继承但可以多层继承)
语句(先继承后实现):class A extends B implements C,D,E{ }
7、接口之间可以继承,多继承也可以
public class InterfaceTest {
public static void main(String[] args) {
//可以直接调用接口的静态属性
System.out.println(Flyable.MAX_SPEED);
System.out.println(Flyable.MIN_SPEED);
//实现类覆盖接口中抽象方法后 可以实例化
Plane plane = new Plane();
plane.stop();
}
}
interface Attackable{
void attack();
}
interface Flyable{
//全局常量的定义
public static final int MAX_SPEED = 1000;
int MIN_SPEED = 1; //省略了public static final
//抽象方法的定义
public abstract void fly();
void stop(); //省略了public abstract
}
//实现类
class Plane implements Flyable{
@Override
public void fly() {
System.out.println("flying");
}
@Override
public void stop() {
System.out.println("stop");
}
}
//实现多接口 覆写了接口的所有抽象方法 可以实例化
class Bullet extends Object implements Flyable,Attackable{
@Override
public void attack() {
}
@Override
public void fly() {
}
@Override
public void stop() {
}
}
8、 JDK8的使用:可以定义全局常量、抽象方法、静态方法和默认方法
静态方法:static修饰,只能由接口调用(实现类不能使用)
默认方法:
- default修饰(实现类的对象可以调用,接口不能调用,非静态);
- 如果实现类中重写了接口中的方法,则调用的是重写的方法;
- 如果子类(实现类)继承的父类与实现的接口存在同名同参的默认方法,且子类(实现类)没有重写此方法,则调用时优先调用父类的该方法(若子类重写了该方法,则调用的是子类重写的方法);
- 如果实现类实现了多个接口(无继承),且多个接口中存在同名同参的默认方法,若子类没有重写该方法,则会出现接口冲突的错误,实现类必须重写该默认方法;
- 在子类(实现类)的方法中调用父类、接口中的被重写的方法;
//子类(实现类)的定义
class subCompare extends superCompare implements Compare{
//重写接口中的默认方法 去掉了default
public void compare3(){
System.out.println("实现类中重写的compare2()方法");
}
public void myMethod(){
//调用自己的重写的compare3方法
compare3();
//调用父类的compare3方法
super.compare3();
//调用接口的compare3方法
Compare.super.compare3();
}
}
三、内部类
JAVA允许一个类A声明在另一个类B中,类A称为内部类,类B为外部类;分为成员内部类(静态、非静态)和局部内部类(方法、构造器、代码块中)
class A{
//非静态成员内部类
class B{
}
//静态成员内部类
static class C{
}
//代码块中声明局部内部类
{
class D{
}
}
//构造器中声明局部内部类
public A(){
class E{
}
}
//方法中声明局部内部类
public void method(){
class F{
}
}
}
成员内部类:
1、作为一个类:可以定义属性、方法和构造器等;可以用final修饰,既不能继承,若没有final则可以继承;可以用abstract修饰,
2、作为外部类的成员:可以调用外部类的结构;可以被static修饰;可以被四种不同权限修饰;
局部内部类:
1、在局部内部类的方法中,如果要调用局部内部类所声明的方法中的局部变量,则必须将该变量加final修饰(即常量);
//局部内部类:在方法中声明类
public void method(){
int num = 10; //final可以省略
class G{
public void show(){
System.out.println(num); //10
}
}
}
内部类实例的创建:
//创建静态成员内部类的对象
A.C c = new A.C();
//创建非静态成员类的对象
A a = new A();
A.B b = a.new B();