Java八大基本类型及大小?

Java八大基本类型包括四种整型、两种浮点型、一种字符型和字符型。

整型:

  • byte:1字节(8位)
  • short:2字节(16位)
  • int:4字节(32位)
  • long:8字节(64位)

浮点型:

  • float:4字节(32位)
  • double:8字节(64位)

字符型:

  • char:2字节(16位)

布尔型:

  • boolean:大小没有明确,一般默认1位

数组和集合的区别是什么?怎么初始化它们?

区别

数据类型:数组只能存储同一类型的元素。而集合可以存储不同类型的元素。

长度:数组的长度是固定的,一旦创建就无法改变。集合的长度是动态的,可以根据需要进行增加或减少。

功能:

  • 数组提供了一些基本的操作方法,如访问、赋值、排序等。
  • 集合提供了多种操作方法,如添加、删除、查找、排序、遍历等。并支持更多的高级功能,如迭代器、集合间的操作。

初始化

数组初始化

1
2
3
4
5
6
7
8
// 静态初始化
int[] arr1 = {1, 2, 3, 4, 5};

// 动态初始化
int[] arr2 = new int[5];
arr2[0] = 1;
arr2[1] = 2;
// ...

列表初始化

1
2
3
4
5
6
7
8
// 使用构造方法
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
// ...

// 使用工厂方法
ArrayList<Integer> list2 = ArrayList.of(1, 2, 3, 4, 5);

重写和重载的区别?

重写

  • 发生在子类和父类之间,子类重写定义父类中的方法、方法名、参数列表和返回类型必须相同。
  • 重写用于实现多态性,子类对象可以根据自身特性对继承的方法进行个性化的实现。
1
2
3
4
5
6
7
8
9
10
11
12
class Animal {
void eat() {
System.out.println("Animal is eating");
}
}

class Dog extends Animal {
@Override
void eat() {
System.out.println("Dog is eating");
}
}

重载

  • 发生在同一个类中,同名方法的参数个数不同,返回类型可以相同也可以不同。

  • 重载用于提供更多方法的选择,使得方法调用更灵活,便于使用不同的参数类型或个数来调用同名方法。

1
2
3
4
5
6
7
8
9
class Calculator {
int add(int a, int b) {
return a + b;
}

double add(double a, double b) {
return a + b;
}
}

List,Set,Map三者区别?

List Set Map
存储有序的元素集合,可以有重复元素 存储无需,不重复的元素集合 key-value映射关系,键不重复但值可以重复
可以通过索引访问元素,类似于数组 不支持通过索引访问元素 可以通过key访问值,类似于字典
常用实现类有 ArrayList、LinkedList、Vector 常用实现类有HashSet、TreeSet 通常实现类有HashMap、TreeMap、LinkedHashMap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// List 示例
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Apple"); // 可以添加重复元素
System.out.println(list); // 输出:[Apple, Banana, Apple]

// Set 示例
Set<String> set = new HashSet<>();
set.add("Apple");
set.add("Banana");
set.add("Apple"); // 重复元素不会被添加
System.out.println(set); // 输出:[Apple, Banana]

// Map 示例
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Apple", 3); // 后面的值会覆盖前面的值
System.out.println(map); // 输出:{Apple=3, Banana=2}

创建线程的三种方法是什么?

1、继承Thread类

2、实现Runnable接口

3、直接使用匿名内部类new Thread()

继承Thread类

  • 创建一个类并继承 Thread 类。
  • 重写 run() 方法,在该方法中定义线程要执行的任务。
  • 创建该类的实例并调用 start() 方法启动线程。
1
2
3
4
5
6
7
8
9
10
11
12
class MyThread extends Thread {
public void run() {
System.out.println("Thread running");
}
}

public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}

实现Runnable

  • 创建一个类实现Runnable接口
  • 实现接口中的run()方法
  • 创建该类的实例,将其作为参数传递给Thread类的构造方法,并调用start()方法启动线程。
1
2
3
4
5
6
7
8
9
10
11
12
class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable running");
}
}

public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
}

匿名内部类

可以通过匿名类的方法直接创建线程对象

1
2
3
4
5
6
Thread thread = new Thread(new Runnable() {
public void run() {
System.out.println("Anonymous Runnable running");
}
});
thread.start();

Spring常用的注解?

  1. @Component:用于标识一个类为 Spring 的组件,会被 Spring 自动扫描并纳入 Spring 容器管理。
  2. @Controller:用于标识一个类为 Spring MVC 控制器,处理 HTTP 请求。
  3. @Service:用于标识一个类为业务逻辑层的服务类,通常作用与@Service注解类似。
  4. @Repository:用于标识一个类为数据访问层的仓库类,通常用于 DAO 类。
  5. @Autowired:用于自动注入依赖,可以标注在字段、构造方法或者方法上。
  6. @RequestMapping:用于映射 HTTP 请求路径到相应的控制器方法上。
  7. @PathVariable:用于将 URL 中的路径参数绑定到方法的参数上。
  8. @RequestParam:用于将 HTTP 请求参数绑定到方法的参数上。
  9. @ResponseBody:用于将方法返回的对象直接作为 HTTP 响应的内容返回。
  10. @Transactional:用于标识一个方法需要在事务管理下执行。

请说下static关键字,有哪些应用场景?

static 是 Java 中的关键字,可以用来修饰类的成员变量和方法。一般在启动项目的时候,会在内存中初始化一块内存,用于初始化static的变量或者方法,可以理解为,项目一启动这个方法就初始化了,不需要等某处调用再初始化内存,这样好处是调用的速度会快很多。

主要有以下几个应用场景:

静态变量

被所有类的实例共享,可以通过类名直接访问,也成为类变量。

1
2
3
4
5
6
7
class MyClass {
static int count = 0;

public MyClass() {
count++;
}
}

静态方法

不依赖类的实例而直接调动,可以通过类名直接调用,也称为类方法。

1
2
3
4
5
class MathUtils {
public static int add(int a, int b) {
return a + b;
}
}

静态代码块

用来初始化类的静态变量或执行静态方法,在类加载时执行且只执行一次。

1
2
3
4
5
class MyClass {
static {
System.out.println("Class MyClass is loaded.");
}
}

三层结构体系是哪三层?

表现层(Controller):也称为用户界面层,负责与用户交互,接收用户输入并展示处理结果。通常包括用户界面设计、页面展示等。

业务逻辑层(Service):也称为服务层,负责处理业务逻辑,包括数据处理、业务规则、流程控制等。通常包括业务逻辑的实现、业务流程的管理等。

数据访问层(Dao):也称为持久化层,负责与数据源进行交互,包括数据库、文件系统等。通常包括数据的读取、写入、更新、删除等操作。

这种三层结构的设计有利于降低系统的耦合度,提高系统的可维护性和扩展性,使各层的职责更加清晰明确。

拆箱和装箱概述

拆箱和装箱是Java中与基本数据类型和包装类之间相互转换的概念。

拆箱

拆箱的意思是将包装类转换成基本类型,比如将Integer转换成int类型

装箱

装箱的意思就是将基本类型转换成它的包装类,比如就将int转换成Integer类型。

代码演示

1
2
3
4
5
6
7
8
9
10
11
12
13
// 装箱
int i = 10;
Integer integer = Integer.valueOf(i);

// 拆箱
Integer integer = Integer.valueOf(10);
int i = integer.intValue();

// 自动装箱
Integer a = 10; // 相当于 Integer a = Integer.valueOf(10);

// 自动拆箱
int b = a; // 相当于 int b = a.intValue();

需要注意的是,过度频繁地进行装箱和拆箱操作可能会影响性能,因此在性能要求较高的场景下,需要注意避免不必要的装箱和拆箱操作。

Web Services概述

Web服务(Web Services)是一种基于网络的应用程序接口(API),它使用标准的 HTTP 协议来进行通信,通过网络传输数据和交换信息。Web服务通常采用 XML 格式来描述和传输数据,可以在不同的平台和编程语言之间进行通信。

Web服务通常包括以下几个关键技术和标准:

  1. SOAP(Simple Object Access Protocol):一种基于 XML 的消息协议,用于在网络上交换结构化的和类型化的信息。SOAP 定义了消息的格式和规范,使得不同平台和编程语言之间可以进行通信。
  2. WSDL(Web Services Description Language):一种用于描述 Web 服务接口的 XML 格式,包括接口的操作、参数、消息格式等信息。WSDL 文件可以帮助客户端了解如何与 Web 服务进行交互。
  3. UDDI(Universal Description, Discovery, and Integration):一种用于注册和发现 Web 服务的协议和规范。通过 UDDI,开发人员可以找到并了解可用的 Web 服务。
  4. RESTful Web 服务:一种基于 REST 架构风格的 Web 服务,使用标准的 HTTP 方法(GET、POST、PUT、DELETE)来进行操作,不依赖于额外的协议和规范。

Web服务可以实现不同系统之间的互操作性,使得不同平台和编程语言的应用程序可以相互通信和交互。它们被广泛应用于分布式系统、微服务架构、云计算等领域。

面向对象概述

面向对象是指将现实中的实物通过对象抽象成一个对象。

面向对象有三大特性:封装继承多态。

封装:封装是将一种数据和操作封装在对象内部,对外隐藏内部细节的机制,通过对外的公共方法来访问和操作对象的数据。

继承:继承是一种通过创建新的类(子类),来集成现有的类,也叫父类,集成父类的属性和方法,同时也可以对父类的方法镜像重写、扩展,也不会影响主类。

多态:多态是一个允许不同类型的对象来执行相同的操作的能力,通过使用接口和方法重写,可以在父类中引用子类对象,或者通过父类来调用子类的方法。

接口和类的区别

接口(Interface)和类(Class)是Java中两种不同的概念,它们有一下主要区别:

  1. 抽象性:
    • 接口可以定义抽象方法和常量,但不能包含具体实现
    • 类可以包含抽象方法和具体方法的实现,也可以包含属性和其他成员变量。
  2. 继承:
    • 类可以通过继承来扩展另一个类,子类可以继承父类的属性和方法。
    • 接口可以通过实现(implements)来使用,一个类可以实现多个接口,实现接口的类必须实现接口中定义的所有方法。
  3. 多态性:
    • 类的多态性是指子类可以替换父类对象的特性。
    • 接口的多态性指的是实现接口的类可以当做相同类型来处理。
  4. 实例化:
    • 类可以被实例化为对象,可以创建类的实例。
    • 接口不能被实例化,但可以通过实现接口的类来创建实例。
  5. 访问修饰符:
    • 类可以使用public、protected、private和默认(包级私有)访问修饰符。
    • 接口中方法默认为public,且不允许使用其他访问修饰符。

Error和Exception的区别是什么?

Error 类型的错误通常为虚拟机相关错误,如系统崩溃,内存不足,堆栈溢出等,编译器不会对这类错误进行检测,Java应用程序也不应对这类错误进行捕获,一旦这类错误发生,通常应用程序会被终止,仅靠应用程序本身无法恢复。

Exception 类的错误是可以在应用程序中进行捕获并处理的,通常遇到这种错 误,应对其进行处理,使应用程序可以继续正常运行。

SQL数据库

MySQL中索引怎么建立?

如果是使用navicat,可以可视化添加索引,选择合适的字段吗,再选择索引类型就可以了。

如果是使用SQL,索引也分为多种类型,单列索引、唯一索引、聚合索引(复合索引)、全文索引等。

1
2
3
4
5
6
7
8
9
10
11
-- 创建单列索引
ALTER TABLE table_name ADD INDEX index_name (column_name);

-- 创建唯一索引
CREATE UNIQUE INDEX index_name ON table_name (column_name);

-- 创建全文索引
ALTER TABLE table_name ADD FULLTEXT INDEX index_name (column_name);

-- 创建聚合索引(复合索引)
ALTER TABLE table_name ADD INDEX index_name (column1, column2);

索引在哪些情况下失效

  1. 没有正确使用到索引
  2. 数据量过小,数据量过小,使用索引可能还不如不使用索引快
  3. 过多的索引可能也会导致索引失败
  4. 对索引使用了函数操作,函数会导致索引失效
  5. 索引列使用了不等于(!=)操作也导致索引失效

Mysql怎么优化查询效率

1、一般直接添加查询评论较高的字段的索引,直接添加索引是最有效的优化查询效率。

2、使用预检查询(explain)来查找那些索引没有使用到那些字段,分析执行效率

3、不要直接使用select *,需要哪些字段,就查询那些字段,防止返回大量用不上的字段

4、根据查询的字段来建立合适的聚合索引

5、避免全表扫描,可能写的SQL有可能执行的全表扫描,这时我们应该建立所以来避免进行全表扫描

主键和外键的区别

主键(Primary Key)是用来唯一标识每一行记录的字段或字段组合,确保表中每一行都有唯一的标识。

外键(Foreign Key)是一个字段或字段组合,它与另一个表的主键或唯一键形成关联,用来建立两个表之间的关系。

实战题目

请用辗转相除法获取两个数的最大公约数,或者用你自己的方法获取两个数的最大公约数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void test1(){
int a = 48;
int b = 18;
int gcd = this.gcd(a, b);
System.out.println(gcd);
}
public int gcd(int a,int b){
while (b != 0){
int temp = b;
b = a % b;
a = temp;
}
return a;
}

请用自己的方法模拟写出堆栈

这段代码演示了如何使用 LinkedList 来实现堆栈的基本功能,包括压入元素、弹出元素、获取栈顶元素等操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class MyStack{
private LinkedList<T> new LinkedList<>();

// 将元素压入堆栈
public void push(T item){
list.addFirst(item);
}

// 弹出堆栈顶部的元素
public T pop() {
if (isEmpty()) {
throw new IllegalStateException("Stack is empty");
}
return list.getFirst();
}

// 判断堆栈是否为空
public boolean isEmpty() {
return list.isEmpty();
}

// 获取堆栈大小
public int size() {
return list.sise();
}
public static void main(String[] args) {
MyStack<Integer> stack = new MyStack<>();
stack.push(1);
stack.push(2);
stack.push(3);

System.out.println("Stack size: " + stack.size());
System.out.println("Top element: " + stack.peek());
System.out.println("Pop element: " + stack.pop());
System.out.println("Stack size after pop: " + stack.size());
}
}

写出一个多线程,要求输出1–26个字母和数字,且差值输出,即:1 a 2 b 3 c…

1
2
3
4
5
6
7
8
9
10
11
12
13
public static String print(char c){
System.out.print(c+" ");
return "";
}
public static void main(String[] args) {
for (int i = 0; i < 26; i++) {
char ch = (char) ('a' +i);
System.out.print(i+1+ " ");
Thread thread = new Thread(print(ch));

thread.start();
}
}

存在一个包含重复数据的ArrayList,如何做去重操作?请写出2种及以上的解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@org.junit.jupiter.api.Test
public void test3(){
ArrayList<String> data = new ArrayList<>();
data.add("测试1");
data.add("测试2");
data.add("测试3");
data.add("测试4");
data.add("测试5");
data.add("测试4");
System.out.println("去重前:"+data);
// 方法一
System.out.println("map去重前:"+this.test4(data));
// 方法二
List<String> list = data.stream().distinct().collect(Collectors.toList());
System.out.println("stream去重后:"+list);
// 方法三
HashSet<String> hashSet = new HashSet<>(data);
ArrayList<String> arrayList = new ArrayList<>(hashSet);
System.out.println("set去重后:"+arrayList);
}

/**
* 方法一:Map去重
*/
public List<String> test4(List<String> data){
HashMap<String, String> map = new HashMap<>();
for (int i = 0; i < data.size(); i++) {
String s = map.get(data.get(i));
if (null == s){
map.put(data.get(i),data.get(i));
}else {
data.remove(i);
}
}
return data;
}