抽象类、接口和内部类拓展
抽象类
抽象类可以理解为一种框架结构,目的是为了提高协作效率。
就是使用abstract修饰符修饰的类。
如果abstract修饰了一个方法,则这个方法就是抽象方法。
抽象类可以没有抽象方法,但是抽象方法只能存在抽象类里。
抽象类不能实例化但是有构造方法,抽象内必须靠子类实现。
抽象类的本质就是一种约束,一种标准。
抽象类的使用
父类示例代码:
//抽象类
public abstract class Father {
//抽象方法
public abstract void say();
//抽象方法
public abstract void sleep();
}
抽象方法必须没有方法体,而且必须有子类实现。
子类示例代码:
public class Son extends Father {
@Override
public void say() {
System.out.println("say");
}
@Override
public void sleep() {
System.out.println("sleep");
}
}
继承抽象类的子类必须有抽象方法的实现,除非子类也是一个抽象类。
抽象的现实:
因为抽象类必须有子类实现,所以逃脱不了extends关键字。
但是在Java中extends是单继承的,大家更常用的反而是多继承的接口,抽象类也是时代的眼泪了。
接口
接口就是一种规范,一种标准。就是大家都遵守的东西,用现实举例子,比如你要使用usb接口,则必须遵守usb的协议。只要遵守这个协议的的设备,不管是U盘还是耳机还是手机都能使用这个接口。
接口中全是抽象方法,可以被类使用implements继承。跟抽象类一样,所有抽象方法都必须被子类重写实现。
一个类可以继承多个接口,但是只要继承就必须实现。
接口与类的区别
-
声明类的关键字是class,声明接口的关键字是interface 。
-
接口不能实例化。
-
接口没有构造方法。
-
接口中的所有方法都必须是抽象方法。(Java8之后接口中可以使用非抽象方法,使用default关键字修饰)
-
接口不能有属性,除非静态的和常量。
-
接口与其说是被类继承不如说是被类实现。
-
接口支持多继承。
接口的使用
接口示例代码:
//接口声明,命名规则跟类一样。
public interface UserServer {
//接口中的方法,完全写法,正常这些修饰符是默认的。
public abstract void sum();
}
//接口声明,命名规则跟类一样。
public interface UserUiView {
//因为接口中默认所有方法都是public abstract修饰的,所以一般写成以下形式。
void add();
//JDK8新特征,接口中的方法实现。
default void abs(){
System.out.println("我是UserUiView接口中的abs方法。");
}
}
类示例代码:
package com.rsp2012.oopi;
//实现接口的类,命名规则使用接口名+Impl
public class UserServerImpl implements UserServer, UserUiView {
@Override
public void sum() {
System.out.println("我是UserServer接口中的sum方法,被UserServerImpl类实现。");
}
@Override
public void add() {
System.out.println("我是UserUiView接口中的add方法,被UserServerImpl类实现。");
}
}
主程序示例代码:
package com.rsp2012.oopi;
public class Test {
public static void main(String[] args) {
//声明类用来调用方法。
UserServerImpl userServer = new UserServerImpl();
//抽象方法,被子类重写实现。
userServer.add();
//打印结果:我是UserUiView接口中的add方法,被UserServerImpl类实现。
userServer.sum();
//打印结果:我是UserServer接口中的sum方法,被UserServerImpl类实现。
//普通方法,被子类继承。
userServer.abs();
//打印结果:我是UserUiView接口中的abs方法。
}
}
拓展
套娃警告,这里记录了一些特殊的代码写法,这些作者自己都学懵了,仅作记录,以后想通了再更新。
类示例代码:
//外部类
public class Demo17 {
private int id;
public void say() {
System.out.println("外部类方法。");
}
//内部类
public class In {
//内部类可以通过方法直接调用外部类的私有属性
public void getID() {
System.out.println(id);
}
}
}
主程序示例代码:
public class Demo18 {
public static void main(String[] args) {
//声明外部类对象
Demo17 demo17 = new Demo17();
//通过外部类对象来实例化内部类
Demo17.In in = demo17.new In();
//通过内部类对象获取外部类的私有属性
in.getID();
}
}
类示例代码:
public class Demo19 {
private int id;
public static void main(String[] args) {
}
}
//内部,但不完全内部...
class in{
public void getId(){
System.out.println(id);
//报错,无法解析的变量名
}
}
这种写法,也叫内部类但是与上面的示例代码不同,这个内部类不能使用public修饰,也不能拿到外部类的私有属性。某种意义上更像对等的关系吧,目前来说常用来测试代码的时候在下面的内部类里写一个main方法方便测试。
类示例代码:
public class Demo19 {
public static void main(String[] args) {
}
//局部内部类
public void test(){
class in{
public void say(){
System.out.println("你好。");
}
}
}
}
局部内部类自我理解就是跟局部变量一样的东西,理论上这个类应该只在调用这个方法的时候才有。
示例代码:
public class Demo19 {
public static void main(String[] args) {
//匿名类,不用将实例化的对象保存在变量中。
new Test().say();
//打印结果:类测试方法。
//接口匿名实现,new接口的语句可以用lambda代替
new UserService() {
@Override
public void hello() {
System.out.println("接口测试方法");
}
}.hello();
//打印结果:接口测试方法
}
}
class Test {
public void say() {
System.out.println("类测试方法。");
}
}
interface UserService {
void hello();
}
据说Android里面全是这些玩意儿,
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人