面试的一些问题汇总

本文着重回顾了Java中抽象类和接口的区别,包括定义、特点、语法和设计上的差异。同时介绍了Mybatis与Redis端口配置,以及@Controller和@RestController的使用技巧。还涵盖了StringBuilder与StringBuffer的线程安全比较。适合初学者和急需补全基础的开发者阅读。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

发现一个问题,因为毕设做的是python自然语言处理方向,我的上一个Java项目距今已有半年了,好多概念和基础的点现在说实话忘得有点多了,唉,加油抓紧时间补补回来吧,真难受。

抽象类和接口的区别

抽象类

在Java中被abstract关键字修饰的类称为抽象类,被abstract关键字修饰的方法称为抽象方法,抽象方法只有方法的声明,没有方法体。抽象类是用来捕捉子类的通用特性的 。它不能被实例化,只能被用作子类的超类。抽象类是被用来创建继承层级里子类的模板。

特点

1、抽象类不能被实例化,即不能使用new关键字来实例化对象,只能被继承

2、包含抽象方法的一定是抽象类,但是抽象类不一定含有抽象方法

3、抽象类中的抽象方法的修饰符只能为public或者protected,默认为public;

4、抽象类中的抽象方法只有方法体,没有具体实现;

5、如果一个子类实现了父类(抽象类)的所有抽象方法,那么该子类可以不必是抽象类,否则就是抽象类

6、抽象类可以包含属性、方法、构造方法,但是构造方法不能用于实例化,主要用途是被子类调用。

接口

Java中接口使用interface关键字修饰。接口是抽象方法的集合。如果一个类实现了某个接口,那么它就继承了这个接口的抽象方法。这就像契约模式,如果实现了这个接口,那么就必须确保使用这些方法。接口只是一种形式,接口自身不能做任何事情。

接口中可以含有 变量和方法。但是要注意,接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误),而方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误),并且接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。从这里可以隐约看出接口和抽象类的区别,接口是一种极度抽象的类型,它比抽象类更加“抽象”,并且一般情况下不在接口中定义变量

允许一个类遵循多个特定的接口。如果一个非抽象类遵循了某个接口,就必须实现该接口中的所有方法。对于遵循某个接口的抽象类,可以不实现该接口中的抽象方法。

特点

1、接口可以包含变量、方法;变量被隐式指定为public static final,方法被隐式指定为public abstract(JDK1.8之前);

2、接口支持多继承,即一个接口可以extends多个接口,间接的解决了Java中类的单继承问题;

3、一个类可以实现多个接口

4、JDK1.8中对接口增加了新的特性:

4.1、默认方法(default method):JDK 1.8允许给接口添加非抽象的方法实现,但必须使用default关键字修饰;定义了default的方法可以不被实现子类所实现,但只能被实现子类的对象调用;如果子类实现了多个接口,并且这些接口包含一样的默认方法,则子类必须重写默认方法

4.2、静态方法(static method):JDK 1.8中允许使用static关键字修饰一个方法,并提供实现,称为接口静态方法。接口静态方法只能通过接口调用(接口名.静态方法名)。

语法区别

在这里插入图片描述

设计区别

抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。

飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。
如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。

抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。

对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。

1、如果你拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类。
2、如果你想实现多重继承,那么你必须使用接口。由于Java不支持多继承,子类不能够继承多个类,但可以实现多个接口。因此你就可以使用接口来解决它。
3、如果基本功能在不断改变,那么就需要使用抽象类。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类

mybatis 和 redis 端口

一般我用SpringBoot都是直接改成自己端口或者默认了,问我的时候还真的一下子回答不上来了,这边回顾一下。

mysql:3306,也就是properties里的spring.datasource.url=jdbc:mysql://localhost:3306
mybatis:
redis:6379

@RestController和@Controller

@RestController注解相当于@ResponseBody + @Controller合在一起的作用,返回json数据不需要在方法前面加@ResponseBody注解了,但使用@RestController这个注解,就不能返回jsp,html页面,视图解析器无法解析jsp,html页面,@RestController注解其实就是将 return 中的内容以 JSON字符串的形式返回客户端。
如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,配置的视图解析器InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。
例如:本来应该到success.jsp页面的,则其显示success.
如果要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行,当@Controller修饰的时候,Spring 才会认为返回的是一个 视图。
如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。

@Controller和@ResponseBody

@Controller 将当前修饰的类注入SpringBoot IOC容器,使得从该类所在的项目跑起来的过程中,这个类就被实例化。当然也有语义化的作用,即代表该类是充当Controller的作用。
@ResponseBody 它的作用是指该类中所有的API接口返回的数据,甭管你对应的方法返回Map或是其他Object,它会以Json字符串的形式返回给客户端,如果返回的是String类型,则仍然是String。
假如返回类型是map,但是没有加@ResponseBody注解,只有@Controller修饰的时候,Spring以为会返回一个View(也就是MVC中的那C)但是返回的东西却是一个Map,页面会报错。

StringBuilder和StringBuffer

String 类中使用 final 关键字修饰字符数组来保存字符串, private final char
value[] ,所以 String 对象是不可变的。

abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
/**
* The count is the number of characters used.
*/
int count;
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}}

而 StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在
AbstractStringBuilder 中也是使用字符数组保存字符串 char[]value 但是没有用 final 关键字修饰,所以这两种对象都是可变的。
StringBuilder 与 StringBuffer 的构造方法都是调用父类构造方法也就是AbstractStringBuilder 实现的。
三者中StringBuilder执行速度最佳,StringBuffer次之,String的执行速度最慢。每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的String 对象。 StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

线程安全性

String、StringBuffer是线程安全的,StringBuilder是线程不安全的(所以如果程序是单线程的使用StringBuilder效率高,如果是多线程使用StringBuffer或者String)。String 中的对象是不可变的,也就可以理解为常量,线程安全。 AbstractStringBuilder 是StringBuilder 与 StringBuffer 的公共父类,定义了一些字符串的基本操作,如expandCapacity 、 append 、 insert 、 indexOf 等公共方法。 StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。 StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值