核心内容摘要
“小南大雷擦狙狙”:一场穿越时空的奇幻之旅
目录
抽象类
1 概述
1.
1 抽象类引入
2 abstract使用格式
1.
1 抽象方法
1.
2 抽象类
1.
3 抽象类的使用
3 抽象类的特征
4 抽象类的细节
5 抽象类存在的意义
接口
1 概述
2 定义格式
3 接口成分的特点
2.
3.
抽象方法
2.
2 常量
2.
3 案例演示
4 基本的实现
2.
1 实现接口的概述
2.
2 实现接口的格式
2.
3 类实现接口的要求和意义
2.
4 类与接口基本实现案例
2.
5 类与接口的多实现案例
5 接口与接口的多继承
6扩展接口的细节
内部类
1 概述
3.
1 什么是内部类
3.
2 什么时候使用内部类
2 内部类的分类
3 成员内部类
4 成员内部类的细节
5 成员内部类面试题
6 成员内部类内存图
7 静态内部类
8 局部内部类
9 匿名内部类【重点】
3.
1 概述
3.
2 格式
3.
2 什么时候用到匿名内部类
3.
3 匿名内部类前提和格式
3.
4 使用方式
3.
5 匿名内部类的特点
3.
6 匿名内部类的使用场景
抽象类
1 概述
1.
1 抽象类引入父类中的方法被它的子类们重写子类各自的实现都不尽相同。
那么父类的方法声明和方法主体只有声明还有意义而方法主体则没有存在的意义了(因为子类对象会调用自己重写的方法)。
换句话说父类可能知道子类应该有哪个功能但是功能具体怎么实现父类是不清楚的由子类自己决定父类只需要提供一个没有方法体的定义即可具体实现交给子类自己去实现。
我们把没有方法体的方法称为抽象方法。
Java语法规定包含抽象方法的类就是抽象类。
抽象方法 没有方法体的方法。
抽象类包含抽象方法的类。
2 abstract使用格式abstract是抽象的意思用于修饰方法方法和类修饰的方法是抽象方法修饰的类是抽象类。
1.
1 抽象方法使用abstract关键字修饰方法该方法就成了抽象方法抽象方法只包含一个方法名而没有方法体。
定义格式修饰符 abstract 返回值类型 方法名 (参数列表)代码举例public abstract void run()
1.
2 抽象类如果一个类包含抽象方法那么该类必须是抽象类。
注意抽象类不一定有抽象方法但是有抽象方法的类必须定义成抽象类。
定义格式abstract class 类名字 { }代码举例public abstract class Animal { public abstract void run() }
1.
3 抽象类的使用要求继承抽象类的子类必须重写父类所有的抽象方法。
否则该子类也必须声明为抽象类。
代码举例// 父类,抽象类 abstract class Employee { private String id; private String name; private double salary; public Employee() { } public Employee(String id, String name, double salary) { this.id id; this.name name; this.salary salary; } // 抽象方法 // 抽象方法必须要放在抽象类中 abstract public void work(); } // 定义一个子类继承抽象类 class Manager extends Employee { public Manager() { } public Manager(String id, String name, double salary) { super(id, name, salary); } //
重写父类的抽象方法 Override public void work() { System.out.println(管理其他人); } } // 定义一个子类继承抽象类 class Cook extends Employee { public Cook() { } public Cook(String id, String name, double salary) { super(id, name, salary); } Override public void work() { System.out.println(厨师炒菜多加点盐...); } } // 测试类 public class Demo10 { public static void main(String[] args) { // 创建抽象类,抽象类不能创建对象 // 假设抽象类让我们创建对象,里面的抽象方法没有方法体,无法执行.所以不让我们创建对象 // Employee e new Employee(); // e.work(); //
创建子类 Manager m new Manager(); m.work(); Cook c new Cook(ap002, 库克,
; c.work(); } }此时的方法重写是子类对父类抽象方法的完成实现我们将这种方法重写的操作也叫做实现方法。
3 抽象类的特征抽象类的特征
总结起来可以说是有得有失有得抽象类得到了拥有抽象方法的能力。
有失抽象类失去了创建对象的能力。
其他成员构造方法实例方法静态方法等抽象类都是具备的。
4 抽象类的细节不需要背只要当idea报错之后知道如何修改即可。
关于抽象类的使用以下为语法上要注意的细节虽然条目较多但若理解了抽象的本质无需死记硬背。
抽象类不能创建对象如果创建编译无法通过而报错。
只能创建其非抽象子类的对象。
理解假设创建了抽象类的对象调用抽象的方法而抽象方法没有具体的方法体没有意义。
抽象类中可以有构造方法是供子类创建对象时初始化父类成员使用的。
理解子类的构造方法中有默认的super()需要访问父类构造方法。
抽象类中不一定包含抽象方法但是有抽象方法的类必定是抽象类。
理解未包含抽象方法的抽象类目的就是不想让调用者创建该类对象通常用于某些特殊的类结构设计。
抽象类的子类必须重写抽象父类中所有的抽象方法否则子类也必须定义成抽象类编译无法通过而报错。
理解假设不重写所有抽象方法则类中可能包含抽象方法。
那么创建对象后调用抽象的方法没有意义。
抽象类存在的意义是为了被子类继承。
理解抽象类中已经实现的是模板中确定的成员抽象类不确定如何实现的定义成抽象方法交给具体的子类去实现。
5 抽象类存在的意义抽象类存在的意义是为了被子类继承否则抽象类将毫无意义。
抽象类可以强制让子类一定要按照规定的格式进行重写。
接口
1 概述我们已经学完了抽象类抽象类中可以用抽象方法也可以有普通方法构造方法成员变量等。
那么什么是接口呢接口是更加彻底的抽象JDK7之前包括JDK7接口中全部是抽象方法。
接口同样是不能创建对象的。
2 定义格式//接口的定义格式 interface 接口名称{ // 抽象方法 } // 接口的声明interface // 接口名称首字母大写满足“驼峰模式”
3 接口成分的特点在JDK7包括JDK7之前接口中的只有包含抽象方法和常量
2.
3.
抽象方法注意接口中的抽象方法默认会自动加上public abstract修饰程序员无需自己手写 按照规范以后接口中的抽象方法建议不要写上public abstract。
因为没有必要啊默认会加上。
2.
2 常量在接口中定义的成员变量默认会加上 public static final修饰。
也就是说在接口中定义的成员变量实际上是一个常量。
这里是使用public static final修饰后变量值就不可被修改并且是静态化的变量可以直接用接口名访问所以也叫常量。
常量必须要给初始值。
常量命名规范建议字母全部大写多个单词用下划线连接。
2.
3 案例演示public interface InterF { // 抽象方法 // public abstract void run(); void run(); // public abstract String getName(); String getName(); // public abstract int add(int a , int b); int add(int a , int b); // 它的最终写法是 // public static final int AGE 12 ; int AGE 12; //常量 String SCHOOL_NAME 黑马程序员; }
4 基本的实现
2.
1 实现接口的概述类与接口的关系为实现关系即类实现接口该类可以称为接口的实现类也可以称为接口的子类。
实现的动作类似继承格式相仿只是关键字不同实现使用implements关键字。
2.
2 实现接口的格式/**接口的实现 在Java中接口是被实现的实现接口的类称为实现类。
实现类的格式:*/ class 类名 implements 接口1,接口2,接口
..{ }从上面格式可以看出接口是可以被多实现的。
大家可以想一想为什么呢
2.
3 类实现接口的要求和意义必须重写实现的全部接口中所有抽象方法。
如果一个类实现了接口但是没有重写完全部接口的全部抽象方法这个类也必须定义成抽象类。
意义接口体现的是一种规范接口对实现类是一种强制性的约束要么全部完成接口申明的功能要么自己也定义成抽象类。
这正是一种强制性的规范。
2.
4 类与接口基本实现案例假如我们定义一个运动员的接口规范代码如下/** 接口接口体现的是规范。
* */ public interface SportMan { void run(); // 抽象方法跑步。
void law(); // 抽象方法遵守法律。
String compittion(String project); // 抽象方法比赛。
}接下来定义一个乒乓球运动员类实现接口实现接口的实现类代码如下package com.bite._03接口的实现; /** * 接口的实现 * 在Java中接口是被实现的实现接口的类称为实现类。
* 实现类的格式: * class 类名 implements 接口1,接口2,接口
..{ * * * } * */ public class PingPongMan implements SportMan { Override public void run() { System.out.println(乒乓球运动员稍微跑一下); } Override public void law() { System.out.println(乒乓球运动员守法); } Override public String compittion(String project) { return 参加project得金牌; } }测试代码public class TestMain { public static void main(String[] args) { // 创建实现类对象。
PingPongMan zjk new PingPongMan(); zjk.run(); zjk.law(); System.out.println(zjk.compittion(全球乒乓球比赛)); } }
2.
5 类与接口的多实现案例类与接口之间的关系是多实现的一个类可以同时实现多个接口。
首先我们先定义两个接口代码如下/** 法律规范接口*/ public interface Law { void rule(); } /** 这一个运动员的规范接口*/ public interface SportMan { void run(); }然后定义一个实现类/** * Java中接口是可以被多实现的 * 一个类可以实现多个接口: Law, SportMan * * */ public class JumpMan implements Law ,SportMan { Override public void rule() { System.out.println(尊长守法); } Override public void run() { System.out.println(训练跑步); } }从上面可以看出类与接口之间是可以多实现的我们可以理解成实现多个规范这是合理的。
5 接口与接口的多继承Java中接口与接口之间是可以多继承的也就是一个接口可以同时继承多个接口。
大家一定要注意类与接口是实现关系接口与接口是继承关系接口继承接口就是把其他接口的抽象方法与本接口进行了合并。
案例演示public interface Abc { void go(); void test(); } /** 法律规范接口*/ public interface Law { void rule(); void test(); } * *
总结 * 接口与类之间是多实现的。
* 接口与接口之间是多继承的。
* */ public interface SportMan extends Law , Abc { void run(); }
6扩展接口的细节不需要背只要当idea报错之后知道如何修改即可。
关于接口的使用以下为语法上要注意的细节虽然条目较多但若理解了抽象的本质无需死记硬背。
当两个接口中存在相同抽象方法的时候该怎么办只要重写一次即可。
此时重写的方法既表示重写1接口的也表示重写2接口的。
实现类能不能继承A类的时候同时实现其他接口呢继承的父类就好比是亲爸爸一样 实现的接口就好比是干爹一样 可以继承一个类的同时再实现多个接口只不过要把接口里面所有的抽象方法全部实现。
实现类能不能继承一个抽象类的时候同时实现其他接口呢实现类可以继承一个抽象类的同时再实现其他多个接口只不过要把里面所有的抽象方法全部重写。
实现类Zi实现了一个接口还继承了一个Fu类。
假设在接口中有一个方法父类中也有一个相同的方法。
子类如何操作呢处理办法一如果父类中的方法体能满足当前业务的需求在子类中可以不用重写。
处理办法二如果父类中的方法体不能满足当前业务的需求需要在子类中重写。
如果一个接口中有10个抽象方法但是我在实现类中只需要用其中一个该怎么办?可以在接口跟实现类中间新建一个中间类适配器类 让这个适配器类去实现接口对接口里面的所有的方法做空重写。
让子类继承这个适配器类想要用到哪个方法就重写哪个方法。
因为中间类没有什么实际的意义所以一般会把中间类定义为抽象的不让外界创建对象
内部类
1 概述
3.
1 什么是内部类将一个类A定义在另一个类B里面里面的那个类A就称为内部类B则称为外部类。
可以把内部类理解成寄生外部类理解成宿主。
3.
2 什么时候使用内部类一个事物内部还有一个独立的事物内部的事物脱离外部的事物无法独立使用人里面有一颗心脏。
汽车内部有一个发动机。
为了实现更好的封装性。
2 内部类的分类按定义的位置来分成员内部内类定义在了成员位置 (类中方法外称为成员位置无static修饰的内部类)静态内部类类定义在了成员位置 (类中方法外称为成员位置有static修饰的内部类)局部内部类类定义在方法内匿名内部类没有名字的内部类可以在方法中也可以在类中方法外。
3 成员内部类成员内部类特点无static修饰的内部类属于外部类对象的。
宿主外部类对象。
内部类的使用格式外部类.内部类。
// 访问内部类的类型都是用 外部类.内部类获取成员内部类对象的两种方式方式一外部直接创建成员内部类的对象外部类.内部类 变量 new 外部类.new 内部类;方式二在外部类中定义一个方法提供内部类的对象案例演示方式一 public class Test { public static void main(String[] args) { // 宿主外部类对象。
// Outer out new Outer(); // 创建内部类对象。
Outer.Inner oi new Outer().new Inner(); oi.method(); } } class Outer { // 成员内部类属于外部类对象的。
// 拓展成员内部类不能定义静态成员。
public class Inner{ // 这里面的东西与类是完全一样的。
public void method(){ System.out.println(内部类中的方法被调用了); } } } 方式二 public class Outer { String name; private class Inner{ static int a 10; } public Inner getInstance(){ return new Inner(); } } public class Test { public static void main(String[] args) { Outer o new Outer(); System.out.println(o.getInstance()); } }
4 成员内部类的细节编写成员内部类的注意点成员内部类可以被一些修饰符所修饰比如 private默认protectedpublicstatic等在成员内部类里面JDK16之前不能定义静态变量JDK16开始才可以定义静态变量。
创建内部类对象时对象中有一个隐含的Outer.this记录外部类对象的地址值。
请参见
6节的内存图详解内部类被private修饰外界无法直接获取内部类的对象只能通过
3节中的方式二获取内部类的对象被其他权限修饰符修饰的内部类一般用
3节中的方式一直接获取内部类的对象内部类被static修饰是成员内部类中的特殊情况叫做静态内部类下面单独学习。
内部类如果想要访问外部类的成员变量外部类的变量必须用final修饰JDK8以前必须手动写finalJDK8之后不需要手动写JDK默认加上。
5 成员内部类面试题请在?地方向上相应代码,以达到输出的内容注意内部类访问外部类对象的格式是外部类名.thispublic class Test { public static void main(String[] args) { Outer.inner oi new Outer().new inner(); oi.method(); } } class Outer { // 外部类 private int a 30; // 在成员位置定义一个类 class inner { private int a 20; public void method() { int a 10; System.out.println(???); // 10 答案a System.out.println(???); // 20 答案this.a System.out.println(???); // 30 答案Outer.this.a } } }
6 成员内部类内存图
7 静态内部类静态内部类特点静态内部类是一种特殊的成员内部类。
有static修饰属于外部类本身的。
总结静态内部类与其他类的用法完全一样。
只是访问的时候需要加上外部类.内部类。
拓展1:静态内部类可以直接访问外部类的静态成员。
拓展2:静态内部类不可以直接访问外部类的非静态成员如果要访问需要创建外部类的对象。
拓展3:静态内部类中没有银行的Outer.this。
内部类的使用格式外部类.内部类。
静态内部类对象的创建格式外部类.内部类 变量 new 外部类.内部类构造器;调用方法的格式调用非静态方法的格式先创建对象用对象调用调用静态方法的格式外部类名.内部类名.方法名();案例演示// 外部类Outer01 class Outer01{ private static String sc_name 黑马程序; // 内部类: Inner01 public static class Inner01{ // 这里面的东西与类是完全一样的。
private String name; public Inner01(String name) { this.name name; } public void showName(){ System.out.println(this.name); // 拓展:静态内部类可以直接访问外部类的静态成员。
System.out.println(sc_name); } } } public class InnerClassDemo01 { public static void main(String[] args) { // 创建静态内部类对象。
// 外部类.内部类 变量 new 外部类.内部类构造器; Outer
Inner01 in new Outer
Inner01(张
; in.showName(); } }
8 局部内部类局部内部类定义在方法中的类。
定义格式:class 外部类名 { 数据类型 变量名; 修饰符 返回值类型 方法名(参数列表) { // … class 内部类 { // 成员变量 // 成员方法 } } }
9 匿名内部类【重点】
3.
1 概述匿名内部类是内部类的简化写法。
他是一个隐含了名字的内部类。
开发中最常用到的内部类就是匿名内部类了。
3.
2 格式new 类名或者接口名() { 重写方法; };包含了继承或者实现关系方法重写创建对象所以从语法上来讲这个整体其实是匿名内部类对象
3.
2 什么时候用到匿名内部类实际上如果我们希望定义一个只要使用一次的类就可考虑使用匿名内部类。
匿名内部类的本质作用是为了简化代码。
之前我们使用接口时似乎得做如下几步操作定义子类重写接口中的方法创建子类对象调用重写后的方法interface Swim { public abstract void swimming(); } //
定义接口的实现类 class Student implements Swim { //
重写抽象方法 Override public void swimming() { System.out.println(狗刨式...); } } public class Test { public static void main(String[] args) { //
创建实现类对象 Student s new Student(); //
调用方法 s.swimming(); } }我们的目的最终只是为了调用方法那么能不能简化一下把以上四步合成一步呢匿名内部类就是做这样的快捷方式。
3.
3 匿名内部类前提和格式匿名内部类必须继承一个父类或者实现一个父接口。
匿名内部类格式new 父类名或者接口名(){ // 方法重写 Override public void method() { // 执行语句 } };
3.
4 使用方式以接口为例匿名内部类的使用代码如下interface Swim { public abstract void swimming(); } public class Demo07 { public static void main(String[] args) { // 使用匿名内部类 new Swim() { Override public void swimming() { System.out.println(自由泳...); } }.swimming(); // 接口 变量 new 实现类(); // 多态,走子类的重写方法 Swim s2 new Swim() { Override public void swimming() { System.out.println(蛙泳...); } }; s
swimming(); s
swimming(); } }
3.
5 匿名内部类的特点定义一个没有名字的内部类这个类实现了父类或者父类接口匿名内部类会创建这个没有名字的类的对象
3.
6 匿名内部类的使用场景通常在方法的形式参数是接口或者抽象类时也可以将匿名内部类作为参数传递。
代码如下interface Swim { public abstract void swimming(); } public class Demo07 { public static void main(String[] args) { // 普通方式传入对象 // 创建实现类对象 Student s new Student(); goSwimming(s); // 匿名内部类使用场景:作为方法参数传递 Swim s3 new Swim() { Override public void swimming() { System.out.println(蝶泳...); } }; // 传入匿名内部类 goSwimming(s