Java基础系列文章
Java基础(一):语言概述
Java基础(二):原码、反码、补码及进制之间的运算
Java基础(三):数据类型与进制
Java基础(四):逻辑运算符和位运算符
Java基础(六):数组
Java基础(七):面向对象编程
Java基础(八):封装、继承、多态性
Java基础(九):Object 类的使用
Java基础(十):关键字static、代码块、关键字final
Java基础(十一):抽象类、接口、内部类
由来
没有具体的实例
,这样的类叫做抽象类被abstract修饰的类
被abstract修饰没有方法体的方法
抽象类的语法格式
[权限修饰符] abstract class 类名{
}
[权限修饰符] abstract class 类名 extends 父类{
}
抽象方法的语法格式
[其他修饰符] abstract 返回值类型 方法名([形参列表]);
举例:
public abstract class Animal {
public abstract void eat();
}
public class Cat extends Animal {
public void eat (){
System.out.println("小猫吃鱼和猫粮");
}
}
public class CatTest {
public static void main(String[] args) {
// 创建子类对象
Cat c = new Cat();
// 调用eat方法
c.eat();
}
}
所有
的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类
注意事项
interface
关键字[修饰符] interface 接口名{
//接口的成员列表:
// 公共的静态常量
// 公共的抽象方法
// 公共的默认方法(JDK1.8以上)
// 公共的静态方法(JDK1.8以上)
// 私有方法(JDK1.9以上)
}
举例:
public interface USB3{
//静态常量
long MAX_SPEED = 500*1024*1024;//500MB/s
//抽象方法
void in();
void out();
//默认方法
default void start(){
System.out.println("开始");
}
default void stop(){
System.out.println("结束");
}
//静态方法
static void show(){
System.out.println("USB 3.0可以同步全速地进行读写操作");
}
}
public static final
可以省略public abstract
可以省略默认方法
和静态方法
:
除此之外,接口中没有构造器,没有初始化块,因为接口中没有成员变量需要动态初始化
implements
,类似于被继承) implements
关键字【修饰符】 class 实现类 implements 接口{
// 重写接口中抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
// 重写接口中默认方法【可选】
}
【修饰符】 class 实现类 extends 父类 implements 接口{
// 重写接口中抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
// 重写接口中默认方法【可选】
}
注意
重写接口中所有抽象方法
【修饰符】 class 实现类 implements 接口1,接口2,接口3。。。{
// 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
// 重写接口中默认方法【可选】
}
【修饰符】 class 实现类 extends 父类 implements 接口1,接口2,接口3。。。{
// 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
// 重写接口中默认方法【可选】
}
extends
关键字,子接口继承父接口的方法定义父接口:
public interface Chargeable {
void charge();
void in();
void out();
}
定义子接口:
public interface UsbC extends Chargeable,USB3 {
void reverse();
}
定义子接口的实现类:
public class TypeCConverter implements UsbC {
@Override
public void reverse() {
System.out.println("正反面都支持");
}
@Override
public void charge() {
System.out.println("可充电");
}
@Override
public void in() {
System.out.println("接收数据");
}
@Override
public void out() {
System.out.println("输出数据");
}
}
接口的不同实现类:
public class Mouse implements USB3 {
@Override
public void out() {
System.out.println("发送脉冲信号");
}
@Override
public void in() {
System.out.println("不接收信号");
}
}
public class KeyBoard implements USB3{
@Override
public void in() {
System.out.println("不接收信号");
}
@Override
public void out() {
System.out.println("发送按键信号");
}
}
测试类:
public class TestComputer {
public static void main(String[] args) {
Computer computer = new Computer();
USB3 usb = new Mouse();
computer.setUsb(usb);
usb.start();
usb.out();
usb.in();
usb.stop();
System.out.println("--------------------------");
usb = new KeyBoard();
computer.setUsb(usb);
usb.start();
usb.out();
usb.in();
usb.stop();
}
}
静态方法
和静态常量
public class TestUSB3 {
public static void main(String[] args) {
//通过“接口名.”调用接口的静态方法 (JDK8.0才能开始使用)
USB3.show();
//通过“接口名.”直接使用接口的静态常量
System.out.println(USB3.MAX_SPEED);
}
}
接口名.
”进行调用即可
public class TestMobileHDD {
public static void main(String[] args) {
//创建实现类对象
MobileHDD b = new MobileHDD();
//通过实现类对象调用重写的抽象方法,以及接口的默认方法,如果实现类重写了就执行重写的默认方法,如果没有重写,就执行接口中的默认方法
b.start();
b.in();
b.stop();
//通过接口名调用接口的静态方法
// MobileHDD.show();
// b.show();
Usb3.show();
}
}
类优先原则
定义接口:
public interface Friend {
default void date(){//约会
System.out.println("吃喝玩乐");
}
}
定义父类:
public class Father {
public void date(){//约会
System.out.println("爸爸约吃饭");
}
}
定义子类:
public class Son extends Father implements Friend {
@Override
public void date() {
//(1)不重写默认保留父类的
//(2)调用父类被重写的
// super.date();
//(3)保留父接口的
// Friend.super.date();
//(4)完全重写
System.out.println("跟康师傅学Java");
}
}
定义测试类:
public class TestSon {
public static void main(String[] args) {
Son s = new Son();
s.date();
}
}
super.方法名()
类名.super.方法名()
接口冲突(左右为难)
声明接口:
public interface BoyFriend {
default void date(){//约会
System.out.println("神秘约会");
}
}
选择保留其中一个,通过“接口名.super.方法名
"的方法选择保留哪个接口的默认方法
public class Girl implements Friend,BoyFriend{
@Override
public void date() {
//(1)保留其中一个父接口的
// Friend.super.date();
// BoyFriend.super.date();
//(2)完全重写
System.out.println("跟康师傅学Java");
}
}
另一个父接口:
public interface USB2 {
//静态常量
long MAX_SPEED = 60*1024*1024;//60MB/s
//抽象方法
void in();
void out();
//默认方法
public default void start(){
System.out.println("开始");
}
public default void stop(){
System.out.println("结束");
}
//静态方法
public static void show(){
System.out.println("USB 2.0可以高速地进行读写操作");
}
}
子接口:
public interface USB extends USB2,USB3 {
@Override
default void start() {
System.out.println("Usb.start");
}
@Override
default void stop() {
System.out.println("Usb.stop");
}
}
此时在子类中想要引用父类或父接口的同名的常量或成员变量时,就会有冲突问题
父类和父接口:
public class SuperClass {
int x = 1;
}
public interface SuperInterface {
int x = 2;
int y = 2;
}
public interface MotherInterface {
int x = 3;
}
子类:
public class SubClass extends SuperClass implements SuperInterface,MotherInterface {
public void method(){
// System.out.println("x = " + x);//模糊不清
System.out.println("super.x = " + super.x);
System.out.println("SuperInterface.x = " + SuperInterface.x);
System.out.println("MotherInterface.x = " + MotherInterface.x);
System.out.println("y = " + y);//没有重名问题,可以直接访问
}
}
静态方法
默认方法
什么是内部类
内部类(InnerClass)
外部类(OuterClass)
为什么要声明内部类呢?
内部类的分类
概述
静态内部类
,否则声明为非静态内部类
语法格式:
[修饰符] class 外部类{
[其他修饰符] [static] class 内部类{
}
}
成员内部类的使用特征,概括来讲有如下两种角色:
类的成员的角色
:
类的角色
:
注意点:
创建成员内部类对象
外部类名.静态内部类名 变量 = 外部类名.静态内部类名();
变量.非静态方法();
外部类名 变量1 = new 外部类();
外部类名.非静态内部类名 变量2 = 变量1.new 非静态内部类名();
变量2.非静态方法();
举例:
public class TestMemberInnerClass {
public static void main(String[] args) {
//创建静态内部类实例,并调用方法
Outer.StaticInner inner = new Outer.StaticInner();
inner.inFun();
//调用静态内部类静态方法
Outer.StaticInner.inMethod();
System.out.println("*****************************");
//创建非静态内部类实例(方式1),并调用方法
Outer outer = new Outer();
Outer.NoStaticInner inner1 = outer.new NoStaticInner();
inner1.inFun();
//创建非静态内部类实例(方式2)
Outer.NoStaticInner inner2 = outer.getNoStaticInner();
inner1.inFun();
}
}
class Outer{
private static String a = "外部类的静态a";
private static String b = "外部类的静态b";
private String c = "外部类对象的非静态c";
private String d = "外部类对象的非静态d";
static class StaticInner{
private static String a ="静态内部类的静态a";
private String c = "静态内部类对象的非静态c";
public static void inMethod(){
System.out.println("Inner.a = " + a);
System.out.println("Outer.a = " + Outer.a);
System.out.println("b = " + b);
}
public void inFun(){
System.out.println("Inner.inFun");
System.out.println("Outer.a = " + Outer.a);
System.out.println("Inner.a = " + a);
System.out.println("b = " + b);
System.out.println("c = " + c);
// System.out.println("d = " + d);//不能访问外部类的非静态成员
}
}
class NoStaticInner{
private String a = "非静态内部类对象的非静态a";
private String c = "非静态内部类对象的非静态c";
public void inFun(){
System.out.println("NoStaticInner.inFun");
System.out.println("Outer.a = " + Outer.a);
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("Outer.c = " + Outer.this.c);
System.out.println("c = " + c);
System.out.println("d = " + d);
}
}
public NoStaticInner getNoStaticInner(){
return new NoStaticInner();
}
}
语法格式:
[修饰符] class 外部类{
[修饰符] 返回值类型 方法名(形参列表){
[final/abstract] class 内部类{
}
}
}
举例:
public class TestLocalInner {
public static void main(String[] args) {
Outer.outMethod();
System.out.println("-------------------");
Outer out = new Outer();
out.outTest();
System.out.println("-------------------");
Runner runner = Outer.getRunner();
runner.run();
}
}
class Outer{
public static void outMethod(){
System.out.println("Outer.outMethod");
final String c = "局部变量c";
class Inner{
public void inMethod(){
System.out.println("Inner.inMethod");
System.out.println(c);
}
}
Inner in = new Inner();
in.inMethod();
}
public void outTest(){
class Inner{
public void inMethod1(){
System.out.println("Inner.inMethod1");
}
}
Inner in = new Inner();
in.inMethod1();
}
public static Runner getRunner(){
class LocalRunner implements Runner{
@Override
public void run() {
System.out.println("LocalRunner.run");
}
}
return new LocalRunner();
}
}
interface Runner{
void run();
}
一次性
的,那么我们“费尽心机”的给它取名字,就显得多余语法格式:
new 父类([实参列表]){
重写方法...
}
new 父接口(){
重写方法...
}
举例1:使用匿名内部类的对象直接调用方法:
interface A{
void a();
}
public class Test{
public static void main(String[] args){
new A(){
@Override
public void a() {
System.out.println("aaaa");
}
}.a();
}
}
举例2:通过父类或父接口的变量多态引用匿名内部类的对象
interface A{
void a();
}
public class Test{
public static void main(String[] args){
A obj = new A(){
@Override
public void a() {
System.out.println("aaaa");
}
};
obj.a();
}
}
举例3:匿名内部类的对象作为实参
interface A{
void method();
}
public class Test{
public static void test(A a){
a.method();
}
public static void main(String[] args){
test(new A(){
@Override
public void method() {
System.out.println("aaaa");
}
});
}
}