中兴面试-Java开发

1、Springboot框架,yarn是怎么配置的

Spring Boot 本身没有直接的配置或集成与 YARN (Yet Another Resource Negotiator) 的特性,YARN是Hadoop的一个资源管理和作业调度平台。如果你想在 YARN 上运行Spring Boot应用,你需要考虑将你的Spring Boot应用打包为一个可执行的jar,并使用 YARN 提供的提交工具将其提交到一个YARN集群。如果你想要实现特定的集成,你可能需要考虑使用Spring for Apache Hadoop或其他相关的库。

2、Spring 框架是怎么实现ioc?

在Spring框架中,IoC(Inversion of Control)是通过以下几种方式实现的:

  • Bean工厂:Spring有一个基本的IoC容器称为Bean工厂,负责创建和管理Bean的生命周期。

  • ApplicationContext:这是Bean工厂的扩展,提供了更多的企业级特性,如事件传播,声明式方式的服务等。

  • XML或注解配置:你可以通过XML文件或注解来配置Bean以及Bean之间的依赖关系,Spring IoC容器将使用这些信息来创建和管理Bean的生命周期。

  • 依赖注入:依赖注入是IoC的一种实现方法,它允许你将对象的依赖作为构造函数参数或属性来提供,而不是在对象内部创建依赖。

3、框架为什么要设置ioc?目的是什么

IoC的目的和好处主要包括:

  • 解耦:IoC有助于减少组件之间的依赖关系,使系统更模块化。

  • 易于测试:由于依赖可以在运行时注入,所以更容易进行单元测试和模拟对象的注入。

  • 代码重用:可以更容易地重用和替换对象实现,因为对象实现和对象使用者之间的耦合度降低。

  • 代码更简洁:由于依赖注入和自动装配,代码更简洁,更容易阅读和维护。

  • 集中式的配置管理:通过IoC,可以集中管理Bean的配置,使配置更集中和一致。

综上所述,IoC的目标是提高代码的模块化,可重用性和可维护性,同时降低代码的耦合度和复杂性。

4、0-60不及格,60-80良好,80-100优秀,输入数字输出判断结果,问要如何测试

  • 边界测试:测试边界值,例如输入0, 60, 80, 100。
  • 正常输入测试:测试一些常见的正常值,例如输入30(应返回“不及格”),70(应返回“良好”),90(应返回“优秀”)。
  • 异常输入测试:测试一些异常输入,例如输入负数或超过100的数字。
  • 类型异常测试:测试输入非整数值,如字符串或浮点数,来验证程序的健壮性。

5、int类型有null吗

int 是Java中的一种原始数据类型,它不能为null。Java中有8种基本数据类型,它们都是非对象类型,因此不能赋值为null。但是,Java也提供了与基本数据类型相对应的包装类(如 Integer 对应 int),这些类是对象,可以被赋值为null。

6、8万条员工数据,按照年龄降序顺序返回工号

假设你有一个名为Employees的数据库表格,其中有EmployeeIDAge这两列,你可以使用以下的SQL查询语句来获取工号列表,根据年龄降序排序:

SELECT EmployeeID 
FROM Employees 
ORDER BY Age DESC;

7、Java内部默认的排序是用的什么

  • 对于基本数据类型,它使用快速排序的变体叫做双枢轴快速排序 (Dual-Pivot Quicksort)。该算法是快速排序的优化版本,其可以提供更好的性能。
  • 对于对象数组或集合中的对象(如List),它使用的是归并排序 (MergeSort) 或 Timsort。 Timsort 是归并排序的一种优化版本,它可以提供更稳定和更高效的性能。

8、在设计数据库表的过程中,如何保证查询速度

(1)适当的索引设计

  • 单列索引: 在经常需要查询的列上创建索引,如主键字段。
  • 复合索引: 如果有一组列经常一起出现在查询条件中,可以考虑为它们创建一个复合索引。
  • 索引选择性: 尽可能在选择性好(列中唯一值多)的列上创建索引。

(2) 适当的分区和分片

  • 水平分区: 将表的行分成多个较小的块,可以并行查询多个分区。
  • 垂直分片: 将表的列分成多个较小的表,这样查询只需要访问涉及的列,减少I/O。

(3) 合适的数据库类型

根据业务需求选择合适的数据库,如关系型数据库(MySQL, PostgreSQL等)、NoSQL数据库(MongoDB, Cassandra等)或是时间序列数据库(InfluxDB等)。

(4) 优化SQL查询

  • 避免在查询中使用全表扫描。
  • 适当使用Join操作,但避免过多的多表连接。
  • 避免在WHERE子句中使用非SARGable查询(例如函数或非等值比较)


9、如何提数据库高查询效率

  • 创建索引: 适当地使用索引可以显著提高查询效率。
  • 查询优化: 避免使用 SELECT * ,只获取需要的列。避免在 WHERE 子句中使用非索引列进行计算。
  • 硬件优化: 使用 SSD、增加 RAM、使用更好的网络连接等。
  • 数据库分片: 将数据分布在多个服务器上。
  • 数据库缓存: 利用 Redis 或 Memcached 缓存频繁查询的结果。
  • 正规化: 避免数据冗余,但也要注意不要过度正规化。
  • 使用合适的数据结构: 如选择合适的数据类型、表结构等。

10、Java反射机制

反射允许在运行时访问 Java 对象的类信息,并进行操作。这包括获取类的方法、构造函数、变量等,甚至可以创建对象、调用方法等。

11、值传递和引用传递Java中的值传递和引用传递的区别

  • 值传递: 函数接收参数值的一个副本。原始数据不会被改变。
  • 引用传递: 函数接收一个引用,指向原始数据的内存地址。通过这个引用,你可以修改原始数据。
  • 对于基本数据类型(如 int, double, char 等),传递的是真正的值。
  • 对于对象,传递的是对象引用的值,即内存地址。因此,如果你在方法中改变对象的状态,原始对象的状态也会被改变。但是,如果你在方法中将引用指向另一个对象,原始引用不会改变。

12、抽象类和接口的差别,使用场景

  • 抽象类要被子类继承,接口要被类实现。
  • 接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现。
  • 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
  • 接口是设计的结果,抽象类是重构的结果。
  • 抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别最高。
  • 抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量。
  • 抽象类主要用来抽象类别,接口主要用来抽象功能。
     

13、为了避免类太臃肿,用聚合和组合,这两个方式怎么用?

  • 如果你的“拥有”关系是“部分-整体”的关系,并且两者的生命周期是紧密相关的,那么你应该使用组合。
  • 如果两者是相对独立的,只是偶尔关联或协作,那么你应该使用聚合。
  • 聚合是一种弱关联关系;组合是一种强关联关系。

  • 在聚合关系中的两个类(或实体)的生命周期是不同步;但,在组合关系中的两个类(或实体)的生命周期是同步的。
     

14、wait和sleep的差异

wait()sleep() 都是 Java 中用于暂停线程执行的方法,但它们的目的、使用方法和工作机制有所不同。以下是它们之间的主要差异:

  • 来源:

    • wait(): 是 Object 类的方法。因为所有对象都继承自 Object 类,所以任何对象都可以调用 wait() 方法。
    • sleep(): 是 Thread 类的静态方法,调用方式为 Thread.sleep()
  • 目的:

    • wait(): 通常用于实现线程间的同步。当一个线程调用一个对象的 wait() 方法时,它将释放该对象的锁并使自己进入等待状态,直到其他线程调用相同对象的 notify()notifyAll() 方法。
    • sleep(): 用于暂停当前执行的线程指定的毫秒数,不释放任何锁。
  • 同步块:

    • wait(): 必须在同步块或同步方法中调用,否则会抛出 IllegalMonitorStateException
    • sleep(): 不需要在同步块或同步方法中调用。
  • 锁的释放:

    • wait(): 当线程调用 wait() 时,它会释放持有的所有同步资源(锁)。
    • sleep(): 当线程调用 sleep() 时,它不会释放任何持有的锁。
  • 唤醒方式:

    • wait(): 一个调用 wait() 的线程可以通过以下方式被唤醒:其他线程调用同一对象的 notify() 方法、notifyAll() 方法,或 wait() 方法的超时时间到达。
    • sleep(): 线程在指定的时间过后会自动唤醒。当然,也可以被中断,导致抛出 InterruptedException
  • 异常:

    • wait(): 可能会抛出 InterruptedException,所以调用者需要处理这个异常。
    • sleep(): 也可能会抛出 InterruptedException,调用者同样需要处理这个异常。

总结:wait()sleep() 在行为和目的上都有所不同。wait() 主要用于线程间的交互和通信,而 sleep() 主要用于暂停线程执行。在使用时,开发者需要根据具体的使用场景选择适当的方法。

15、Java中的线程池实现以及好处

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExample {

    public static void main(String[] args) {
        // Create a fixed thread pool with 5 threads
        ExecutorService executor = Executors.newFixedThreadPool(5);

        // Submit 10 tasks to thread pool
        for (int i = 1; i <= 10; i++) {
            Runnable worker = new WorkerThread("" + i);
            executor.submit(worker);
        }
        
        // Shutdown the thread pool after all tasks are finished
        executor.shutdown();

        while (!executor.isTerminated()) {
        }

        System.out.println("All threads finished");
    }
}

class WorkerThread implements Runnable {
    private String command;

    public WorkerThread(String s) {
        this.command = s;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " Start. Command = " + command);
        processCommand();
        System.out.println(Thread.currentThread().getName() + " End.");
    }

    private void processCommand() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return this.command;
    }
}

好处:

  • 资源重用:线程的创建和销毁需要时间和系统资源。线程池通过重用已存在的线程,减少了这种开销。

  • 提高响应速度:当任务到达时,线程池中如果有空闲线程,可以立即执行,无需等待线程创建。

  • 提高线程管理性:线程池限制了系统中执行线程的数量。这有助于提高系统的整体性能,并避免由于太多线程而导致的系统性能下降。

  • 提供更多的功能:除了基本的线程池功能外,java.util.concurrent 还提供了定期执行任务和延迟执行任务的功能。

  • 容错性:线程池提供了保护机制,可以处理线程因异常而死亡的情况,并创建新的线程来替代。

  • 资源控制:通过使用固定大小的线程池,可以控制系统中并发线程的最大数量,防止系统因过多线程而耗尽资源。

16、final和abstract能一起用吗

在Java中,finalabstract是互斥的关键字,不能在同一个类或方法上一起使用。abstract意味着类是一个基类,不能被实例化,而且它可能有一些未被实现的方法。而final意味着类不能被继承。由于这两者的含义是矛盾的,所以它们不能一起用。

17、初始化字符串用字面量还是new String(),差异在哪

  • 存储位置:

    • 字面量:当你使用字面量初始化字符串(例如 String s = "hello";),这个字符串值被存储在字符串池中。如果后续有同样的字面量被用来初始化另一个字符串,它会重用字符串池中的这个实例,而不会创建一个新的字符串对象。
    • new String():当你使用new String("hello"),Java 会在堆上创建一个新的字符串实例,即使字符串池中已经存在一个值为 "hello" 的字符串。
  • 对象数量:

    • 字面量:不会创建多余的对象。如果相同的字面量之前已被使用过,那么不会创建新的字符串对象。
    • new String():每次都会创建一个新的对象,即使其内容与已有的对象相同。
  • 性能和内存

    • 字面量:因为可以重用字符串池中的实例,所以使用字面量在性能和内存使用上通常更有优势。
    • new String():可能会导致额外的内存使用,因为每次都在堆上创建新的对象,而且有可能创建了多个内容相同的字符串对象。
  • 使用场景

    • 字面量:在大多数情况下,直接使用字面量是推荐的,因为它更加高效。
    • new String():在某些特定情况下可能会有用,例如,当你明确需要一个新的字符串实例(与池中的实例不同)时。

18、高度是k的二叉树最少和最多分别有多少节点?

  • 最少节点数:高度为k的二叉树至少有k+1个节点(这是一个只有左子节点或只有右子节点的斜树)。
  • 最多节点数:高度为k的二叉树最多有2�+1−12k+1−1个节点(完全二叉树)。

19、数组和链表的区别?这俩在内存开销上的差异?

数组

  • 内存结构:连续的内存空间。
  • 访问:可以进行O(1)时间复杂度的随机访问。
  • 内存开销:较小,只存储数据。

链表

  • 内存结构:不连续的内存空间,每个节点存储数据和指向下一个节点的指针。
  • 访问:O(n)时间复杂度的访问。
  • 内存开销:较大,因为除了数据外,还需要存储指向其他节点的指针

20、普通的线性搜索和二分查找的优势?

线性搜索

  • 优势:不需要数组是有序的。适用于链表和其他非随机访问的数据结构。
  • 时间复杂度:O(n)。

二分查找

  • 优势:非常快速,在已排序的数组中进行搜索的时间复杂度为O(log n)。
  • 限制:只能用于已排序的数组或列表。不适用于链表,因为链表不支持高效的随机访问。

21、字面量的String存在什么问题?

使用字符串字面量主要的问题有以下几点:

  • 不可变性:String类是不可变的,这意味着你不能更改字符串的内容。每次你对字符串做任何修改,都会创建一个新的字符串对象。在重复修改字符串的情况下,这可能导致内存浪费和不必要的性能开销。

  • 安全性:由于字符串池是静态的,因此可能会有安全风险,特别是当涉及到敏感信息时。如果敏感数据(例如密码)被存储为字符串字面量,那么即使原始变量被设置为null或被改写,该数据仍然可能在字符串池中被恶意代码访问。

  • 内存占用:由于Java为了效率和性能的考虑会把字面量字符串存储在字符串池中,如果有大量不再使用的字符串字面量,这些字面量并不会被垃圾回收,这可能导致内存的浪费。

22、字面量String存在哪个空间?

在Java中,字符串字面量是存储在字符串池中的,该池位于Java堆的永久代(PermGen space)或者从Java 8开始的元空间(Metaspace)。永久代和元空间都是Java虚拟机(JVM)的内存区域,用于存储类的元数据、静态变量、方法区等。字面量字符串和其他常量字符串在此被存储和重用,从而提高性能和减少内存使用。

23、多线程操作链表

使用多线程来操作链表可能会引发各种问题,如数据不一致、竞态条件等。因此,当多个线程需要访问和修改链表时,你需要采用适当的同步机制来确保数据的一致性和完整性。为了确保多线程安全,你可以使用synchronized关键字或java.util.concurrent中的锁机制。以下是一个简单的多线程安全链表操作的示例:

import java.util.LinkedList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadSafeLinkedList<T> {

    private final LinkedList<T> list = new LinkedList<>();
    private final Lock lock = new ReentrantLock();

    public void add(T item) {
        lock.lock();
        try {
            list.add(item);
        } finally {
            lock.unlock();
        }
    }

    public T removeFirst() {
        lock.lock();
        try {
            if (list.isEmpty()) {
                return null;
            }
            return list.removeFirst();
        } finally {
            lock.unlock();
        }
    }

    public boolean isEmpty() {
        lock.lock();
        try {
            return list.isEmpty();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadSafeLinkedList<Integer> linkedList = new ThreadSafeLinkedList<>();

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                linkedList.add(i);
                System.out.println("Added: " + i);
            }
        });

        Thread t2 = new Thread(() -> {
            while (!linkedList.isEmpty()) {
                Integer item = linkedList.removeFirst();
                System.out.println("Removed: " + item);
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();
    }
}

23、TCP头部结构

  • 源端口号(Source Port) - 16位: 表示发送方的端口号。

  • 目标端口号(Destination Port) - 16位: 表示接收方的端口号。

  • 序列号(Sequence Number) - 32位: 如果SYN标志位被设置,这表示连接的初始序列号。否则,它表示发送方所发送的数据字节流的第一个字节的序列号。

  • 确认序列号(Acknowledgment Number) - 32位: 如果ACK标志位被设置,这表示接收方期望收到的下一个序列号。因此,确认的序列号是已经成功接收的数据的最后一个字节的序列号加1。

  • 数据偏移(Data Offset) - 4位: 表示TCP头部的大小(单位为32位字)。

  • 保留(Reserved) - 3位: 为将来的使用而保留,目前应设置为0。

  • 控制位(Control Flags) - 9位:

    • URG:紧急指针有效。
    • ACK:确认序列号有效。
    • PSH:Push操作。
    • RST:连接重置。
    • SYN:同步序列号,用于建立连接。
    • FIN:发送方已经完成发送。
  • 窗口大小(Window Size) - 16位: 指定了发送方当前允许接收方发送的数据量(单位为字节)。

  • 校验和(Checksum) - 16位: 用于错误检测,涵盖了TCP头部和数据。

  • 紧急指针(Urgent Pointer) - 16位: 如果URG标志被设置,那么这个字段是有意义的,表示紧急数据的最后一个字节的序列号。

  • 选项和填充(Options and Padding): 这部分的长度是可变的。常见的选项包括最大段大小(MSS)、时间戳、窗口扩大因子等。、

24、交换机与路由器有什么区别

  • 工作层级

    • 交换机:主要在数据链路层(OSI模型的第2层)工作,使用MAC地址进行数据帧的转发。
    • 路由器:在网络层(OSI模型的第3层)工作,使用IP地址进行数据包的路由。
  • 用途和功能

    • 交换机:用于连接同一个局域网内的设备,如电脑、打印机等。它可以学习和存储MAC地址,以确定如何转发数据帧。
    • 路由器:用于连接不同的网络,并根据IP地址路由数据。它还可以执行NAT(网络地址转换)、DHCP(动态主机配置协议)等高级功能。
  • 广播域

    • 交换机:默认情况下,交换机内的所有端口都处于同一广播域。
    • 路由器:每个路由器的接口都在不同的广播域中。
  • 冲突域

    • 交换机:在交换机中,每个端口都是一个单独的冲突域。
    • 路由器:同上,每个路由器端口也是一个单独的冲突域。
  • 表项

    • 交换机:维护一个MAC地址表。
    • 路由器:维护一个或多个路由表。
  • 速度与延迟

    • 交换机:由于直接使用MAC地址转发数据帧,通常延迟较低。
    • 路由器:因为需要查找路由表来决定如何转发数据包,可能会有稍微的延迟。
  • 安全和管理特性

    • 交换机:高级的可管理交换机可以提供VLAN、QoS、链路聚合等功能。
    • 路由器:除了基本的路由功能,还可能提供防火墙、VPN、流量监控等高级特性。
  • 应用场景

    • 交换机:用于扩展局域网,提供更多的端口连接。
    • 路由器:用于连接不同的局域网或连接局域网和广域网,如连接家庭或办公室网络到互联网。
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金州饿霸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值