





把通用的步骤放到抽象类的一个执行方法中,每个步骤定义成抽象方法,子类实现每个步骤的细节,当子类调用父类的执行方法时,如果遇到通用步骤就会调用子类的具体步骤来实现,(注意:新建对象时运行类型和编译类型都是子类的,只是调用了父类的方法而已,而通用步骤的方法子类对父类已经实现,所以调用的还是子类的)

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;
}
}
}

注意:


实现接口时对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();
}
}


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



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();
}
}
