java基础08--抽象类、接口、内部类
抽象类、接口、内部类
一、抽象类
介绍

使用场景

语法

抽象类的注意事项和细节(注意: 1,5,8)



抽象类和普通类的区别
- 不能被实例化,但可以作为父类引用指向子类对象
- 修饰符不能有private,final,static
- 如果有抽象方法抽象类一定要加上abstract
- 继承过程中抽象方法一定要被实现或者继续抽象
模板设计模式
介绍
把通用的步骤放到抽象类的一个执行方法中,每个步骤定义成抽象方法,子类实现每个步骤的细节,当子类调用父类的执行方法时,如果遇到通用步骤就会调用子类的具体步骤来实现,(注意:新建对象时运行类型和编译类型都是子类的,只是调用了父类的方法而已,而通用步骤的方法子类对父类已经实现,所以调用的还是子类的)
案例

package com.bijing.static_.abstract_;
public abstract class Template {
public static void main(String[] args) {
AA aa = new AA();
BB bb = new BB();
aa.getTime();
bb.getTime();
}
public void getTime() {
long startTime = System.currentTimeMillis();
job();
long endTime = System.currentTimeMillis();
System.out.println("运行时间:" + (endTime - startTime));
}
public abstract void job();
}
class AA extends Template {
@Override
public void job() {
long sum = 0;
for (long i = 0; i < 100000; i++) {
sum += i;
}
}
}
class BB extends Template {
@Override
public void job() {
long sum = 0;
for (long i = 0; i < 1000000; i++) {
sum += i;
}
}
}
二、接口
基本介绍

注意:
- 在接口中抽象方法可以不加abstract
- jdk8及以后可以有默认方法但是要加default关键字,如果是静态方法不用加default
接口使用的注意事项和使用细节(注意:4,6,8)


实现接口VS继承类
实现接口时对java单继承的补充
- 当子类继承了父类就自动拥有了父类的功能
- 如果子类需要拓展功能就需要通过实现接口的方式来拓展

接口的多态特性
有点类似向上转型和向下转型

多态传递
//I3实现了I1,I1继承了I2,所以接口I1和I2都可以使用I3的实例
//或者说I3==>I1->I2,I1和I2都可以使用I3的实例
interface I1 extends I2 {
}
interface I2 {
}
class I3 implements I1 {
}
public class Test {
public static void main(String[] args) {
I1 i1 = new I3();
I2 i2 = new I3();
}
}

接口和抽象类的区别
- 接口是对动作的抽象,抽象类是对本质的抽象
- 接口中所有成员变量都是用public static final修饰的
- 接口中没有构造器,没有main方法,因为它不是一个类
- 抽象类是用来继承的(extends),接口是用来实现的(implements)
- 接口是多继承的,抽象类是单继承的
- 接口中声明默认方法要加default,静态方法可以不加
- 接口中可以有静态方法不能有静态代码块,抽象类中可以有静态方法和静态代码块
三、内部类(重点、难点)
基本介绍

类的五大成员:属性,方法,构造器,代码块,内部类
内部类的分类

局部内部类


tips:因为在方法中,所以当成方法的一个局部变量,不过是以类的形式而存在的,所以可以访问外部类的成员但是不能添加访问修饰符,作用域也仅仅在定义它的方法或代码中,要使用也只能在方法中实例化对象
案例:

interface Plants {
void say();
}
class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
void say() {
System.out.println("我是动物" + getName());
}
}
public class LocalInnerClass {
public static void main(String[] args) {
LocalInnerClass localInnerClass = new LocalInnerClass();
localInnerClass.getAnimal();
localInnerClass.getPlants();
}
//局部内部类--继承外部的一般类
void getAnimal() {
class Pig extends Animal {
public Pig(String name) {
super(name);
}
}
Animal animal = new Pig("猪");
animal.say();
}
//局部内部类--实现外部的接口
void getPlants() {
class Tree implements Plants {
String name;
public Tree(String name) {
this.name = name;
}
@Override
public void say() {
System.out.println("我是植物" + this.name);
}
}
Plants plants = new Tree("树");
plants.say();
}
匿名内部类(重要!!!)
匿名内部类的使用

所谓的匿名实则是系统给的我们不知道而已,系统分配为***$1


//前提:必须继承一个父类或实现一个接口
interface Plants02 {
String name = "apple tree";
void say();
}
public class AnonymousInnerClass {
int a = 1;
String name = "pear tree";
public static void main(String[] args) {
AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass();
anonymousInnerClass.getAnimal02();
anonymousInnerClass.getPlant02();
}
//匿名内部类
void getAnimal02() {
//继承类式的
Animal02 dog = new Animal02("二狗") {
public void say() {
int a = 10;
System.out.println("我是" + getName());
System.out.println(a);//10
System.out.println(AnonymousInnerClass.this.a);//1
}
public void sayName() {
}
};
dog.say();
// dog.sayName(),报错是因为dog的编译类型是Animal02,它没有sayName()方法
}
void getPlant02() {
//实现接口式的
Plants02 tree = new Plants02() {
@Override
public void say() {
System.out.println("我是树");
System.out.println(name);//apple tree
System.out.println(AnonymousInnerClass.this.name);//pear tree
}
};
tree.say();
//lambda表达式
Plants02 trees = () -> System.out.println("我是树");
}
}
class Animal02 {
private String name;
public Animal02(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
void say() {
System.out.println("我是动物" + getName());
}
}
注意和匿名对象的区别
//下面的运行类型是Tiger
Animal animal2 = new Tiger();
//下面的运行类型是Outer$2
Animal animal3 = new Tiger() {
};
匿名内部类使用的注意事项和细节
tips:匿名内部类一般都是new 接口名/父类名 (){},创建出来的匿名内部类是“儿子”

public void f1() {
//这边是类
Person p = new Person() {
@Override
public void hi() {
System.out.println("内部hi() ");
}
};
p.hi();
//匿名内部类本身也是对象
new Person() {
@Override
public void hi() {
System.out.println("新的内部hi() ");
}
}.hi();
}


匿名内部类的实践

和传统方法对比:
interface Plant {
void show();
}
public class Use_ {
public static void main(String[] args) {
//使用匿名内部类
f1(new Plant() {
@Override
public void show() {
System.out.println("wo shi plant");
}
});
//传统方法
f1(new Tree());
}
public static void f1(Plant plant) {
plant.show();
}
}
//传统方法
class Tree implements Plant {
@Override
public void show() {
System.out.println("wo shi tree");
}
}
成员内部类

public class OuterClass {
int a = 1;
public static void main(String[] args) {
//调用成员内部类方法
OuterClass outerClass = new OuterClass();
outerClass.useInnerClass();
//创建成员内部类对象,使用成员内部类属性,方法
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
System.out.println(innerClass.name);
innerClass.say();
}
public void useInnerClass() {
InnerClass innerClass = new InnerClass();
innerClass.say();
}
class InnerClass {
String name = "内部类";
int a = 10;
void say() {
System.out.println("我是内部类");
System.out.println(a);//10
System.out.println(OuterClass.this.a);//1
}
}
}
class OtherOuterClass {
public static void main(String[] args) {
// 外部其他类中使用
OuterClass outerClass = new OuterClass();
outerClass.useInnerClass();
//创建成员内部类对象,使用成员内部类属性,方法
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
System.out.println(innerClass.name);
innerClass.say();
}
}

第五点:

第六点:
class OuterClass {
public InnerClass02 getInnerClass() {
return new InnerClass02();
}
class InnerClass {
}
class InnerClass02 {
}
}
class Visit {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
//方式一
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
//方式二
OuterClass.InnerClass02 innerClass02 = outerClass.getInnerClass();
}
}
静态内部类



public class StaticInnerClass {
static int a = 1;
public static void main(String[] args) {
//静态内部类对象创建及使用
InnerClass innerClass = new InnerClass();
innerClass.say();
StaticInnerClass.InnerClass innerClass1 = new InnerClass();
innerClass1.say();
}
static class InnerClass {
int a = 10;
void say() {
System.out.println("我是静态内部类");
System.out.println(a);//10
System.out.println(StaticInnerClass.a);//1
}
}
}
//在其他外部内中使用静态内部类
class OtherOuterClass_ {
public static void main(String[] args) {
StaticInnerClass.InnerClass innerClass = new StaticInnerClass.InnerClass();
innerClass.say();
}
}
