您的位置:首页 > 科技 > 能源 > 四川省住房和城乡建设厅官网电话_开发者选项在哪里打开vivo_app001推广平台官网_成都搜索优化整站优化

四川省住房和城乡建设厅官网电话_开发者选项在哪里打开vivo_app001推广平台官网_成都搜索优化整站优化

2024/12/23 9:35:12 来源:https://blog.csdn.net/qq_45089709/article/details/144075896  浏览:    关键词:四川省住房和城乡建设厅官网电话_开发者选项在哪里打开vivo_app001推广平台官网_成都搜索优化整站优化
四川省住房和城乡建设厅官网电话_开发者选项在哪里打开vivo_app001推广平台官网_成都搜索优化整站优化

以下是一些Java常见面试题:

一、基础知识部分

  1. Java的基本数据类型有哪些?

    • Java有8种基本数据类型,分别是:
      • 整数类型byte(1字节,范围是 - 128到127)、short(2字节,范围是 - 32768到32767)、int(4字节,范围是 - 2147483648到2147483647)、long(8字节)。
      • 浮点类型float(4字节)、double(8字节)。
      • 字符类型char(2字节,用于存储单个字符)。
      • 布尔类型boolean(1位,只有truefalse两个值)。
  2. ==equals()的区别?

    • ==操作符
      • 对于基本数据类型,比较的是它们的值是否相等。例如,int a = 5; int b = 5;a == b的结果是true
      • 对于引用类型,比较的是两个引用是否指向同一个对象。例如,String s1 = new String("hello"); String s2 = new String("hello");s1 == s2的结果是false,因为它们是两个不同的对象。
    • equals()方法
      • 它是Object类中的一个方法,用于比较两个对象的内容是否相等。默认情况下(在Object类中),equals()方法的行为和==相同,比较的是引用。
      • 但是很多类(如String)重写了equals()方法,用于比较对象的内容。例如,对于上面的s1s2s1.equals(s2)的结果是true,因为String类的equals()方法比较的是字符串的内容。
  3. 面向对象的三大特性是什么?请简单解释。

    • 封装
      • 把对象的属性和行为(方法)结合为一个独立的整体,并尽可能隐藏对象的内部细节。例如,将一个类的属性设为private,然后通过publicgetset方法来访问和修改属性,这样就实现了对属性的封装。
    • 继承
      • 允许创建新的类(子类)基于现有的类(父类),子类继承父类的属性和方法,并且可以添加自己的新属性和方法或者重写父类的方法。例如,class Dog extends AnimalDog类可以继承Animal类的eat()方法,并且可以定义自己特有的bark()方法。
    • 多态
      • 指同一个行为(方法)具有多种不同的表现形式。多态有两种实现方式:
        • 方法重载:在同一个类中,方法名相同,但参数列表不同(参数个数、类型、顺序不同)。例如,int add(int a, int b)double add(double a, double b)是方法重载。
        • 方法重写:在子类和父类中,方法名、参数列表和返回类型都相同(子类返回类型可以是父类返回类型的子类型),子类重写父类的方法来改变方法的行为。例如,父类AnimalmakeSound()方法,子类Dog重写这个方法来发出“汪汪”声。
  4. Java中的异常处理机制是怎样的?

    • Java通过try - catch - finally语句块来处理异常。
    • try:包含可能会抛出异常的代码。例如,try { int result = 10 / 0; }(这里会抛出ArithmeticException)。
    • catch:用于捕获并处理try块中抛出的异常。可以有多个catch块来捕获不同类型的异常。例如:
      try {int result = 10 / 0;
      } catch (ArithmeticException e) {System.out.println("除数不能为0");
      }
      
    • finally:无论try块中是否抛出异常,finally块中的代码都会执行。通常用于释放资源,如关闭文件流、数据库连接等。例如:
      FileInputStream fis = null;
      try {fis = new FileInputStream("test.txt");// 读取文件操作
      } catch (FileNotFoundException e) {System.out.println("文件不存在");
      } finally {if (fis!= null) {try {fis.close();} catch (IOException e) {System.out.println("关闭文件流出错");}}
      }
      
  5. 接口和抽象类的区别是什么?

    • 语法层面
      • 抽象类:可以包含抽象方法(没有方法体的方法)和非抽象方法,可以有成员变量(可以是privateprotectedpublic等访问修饰符)。例如:
        abstract class AbstractShape {protected int sides;abstract double area();public void setSides(int sides) {this.sides = sides;}
        }
        
      • 接口:所有方法都是抽象方法(在Java 8之前),并且默认是publicabstract的,接口中的变量默认是publicstaticfinal的。例如:
        interface Shape {double area();static final int DEFAULT_SIDES = 4;
        }
        
    • 设计理念层面
      • 抽象类:用于表示一种抽象的概念,它可以有部分实现,是一种“is - a”(是一种)的关系,子类和抽象类之间是继承关系。例如,Square是一种AbstractShape,可以继承AbstractShape来实现自己的功能。
      • 接口:用于定义一组行为规范,是一种“has - a”(具有)的关系,实现类和接口之间是实现关系。例如,一个类实现了Runnable接口,就表明这个类具有run()这个行为。

二、集合框架部分

  1. 请介绍一下Java中的集合框架。

    • Java集合框架主要包括两大接口:CollectionMap
    • Collection接口
      • 它是所有集合类的根接口,有三个主要的子接口:ListSetQueue
      • List接口:是一个有序的集合,可以包含重复元素。常见的实现类有ArrayList(基于动态数组实现,随机访问效率高)和LinkedList(基于链表实现,插入和删除操作效率高)。
      • Set接口:是一个不允许包含重复元素的集合。常见的实现类有HashSet(基于哈希表实现)和TreeSet(基于红黑树实现,可以对元素进行排序)。
      • Queue接口:用于处理按特定顺序排列的元素,通常是先进先出(FIFO)顺序。常见的实现类有LinkedList(它既实现了List又实现了Queue)和PriorityQueue(根据元素的优先级进行排序)。
    • Map接口
      • 用于存储键 - 值对(key - value pairs),每个键最多对应一个值。常见的实现类有HashMap(基于哈希表实现,查询效率高)、TreeMap(基于红黑树实现,可以根据键进行排序)和LinkedHashMap(可以保持元素插入的顺序)。
  2. ArrayListLinkedList的区别是什么?

    • 数据结构层面
      • ArrayList:是基于动态数组实现的。它在内存中是连续存储的,所以可以通过索引快速访问元素,时间复杂度为 O ( 1 ) O(1) O(1)。例如,ArrayList<String> list = new ArrayList<>(); list.get(3);可以很快地获取到索引为3的元素。
      • LinkedList:是基于链表结构实现的。每个元素(节点)包含数据和指向下一个节点(或上一个节点,对于双向链表)的引用。它在插入和删除操作时,只需要修改节点之间的引用关系,时间复杂度为 O ( 1 ) O(1) O(1)(在特定位置插入或删除),但访问元素需要遍历链表,时间复杂度为 O ( n ) O(n) O(n)。例如,在LinkedList<String> linkedList = new LinkedList<>();中插入一个元素到头部linkedList.addFirst("newElement");操作效率较高。
    • 使用场景层面
      • ArrayList:适合频繁访问元素的场景,如随机读取数组中的元素进行计算或者展示。
      • LinkedList:适合频繁进行插入和删除操作的场景,如实现一个栈或者队列的功能。
  3. HashMap的工作原理是什么?

    • HashMap是基于哈希表(散列表)的数据结构。
    • 它通过put(key, value)方法存储键 - 值对。当调用put方法时,首先会根据keyhashCode()方法计算出一个哈希值(这个哈希值是一个整数),然后通过一定的算法(通常是取余运算)将哈希值映射到数组的一个索引位置(称为桶,bucket)。
    • 如果这个桶中没有元素,就直接将键 - 值对存储在这个位置;如果桶中已经有元素(产生了哈希冲突),HashMap会采用拉链法来处理。即,将新的键 - 值对以链表(在Java 8以后,如果链表长度达到一定阈值,会转换为红黑树来提高性能)的形式存储在这个桶中。
    • 当通过get(key)方法获取值时,同样先计算key的哈希值,找到对应的桶,然后在桶中通过equals()方法(对于键的比较)来查找对应的键 - 值对,找到后返回值。

三、多线程部分

  1. 创建线程有哪几种方式?请简单介绍。

    • 继承Thread
      • 定义一个类继承Thread类,然后重写run()方法。例如:
        class MyThread extends Thread {@Overridepublic void run() {System.out.println("线程执行的内容");}
        }
        public class Main {public static void main(String[] args) {MyThread myThread = new MyThread();myThread.start();}
        }
        
      • 这种方式的缺点是,如果一个类已经继承了其他类,就不能再继承Thread类。
    • 实现Runnable接口
      • 定义一个类实现Runnable接口,并重写run()方法,然后将这个实现类的对象作为参数传递给Thread对象的构造函数。例如:
        class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("线程执行的内容");}
        }
        public class Main {public static void main(String[] args) {Thread thread = new Thread(new MyRunnable());thread.start();}
        }
        
      • 这种方式的优点是可以避免单继承的限制,并且可以更好地实现资源共享,因为多个线程可以共享同一个Runnable对象。
    • 实现Callable接口(结合FutureFutureTask
      • Callable接口类似于Runnable接口,但是它有返回值,并且可以抛出异常。定义一个类实现Callable接口,并重写call()方法。例如:
        import java.util.concurrent.Callable;
        import java.util.concurrent.FutureTask;
        class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {return 10;}
        }
        public class Main {public static void main(String[] args) throws Exception {MyCallable myCallable = new MyCallable();FutureTask<Integer> futureTask = new FutureTask<>(myCallable);Thread thread = new Thread(futureTask);thread.start();System.out.println(futureTask.get());}
        }
        
      • 这种方式可以获取线程执行后的返回值,通过FutureFutureTask来接收和处理返回值。
  2. 线程的生命周期包括哪些状态?

    • 新建(New):当创建一个Thread对象后,线程就处于新建状态。例如,Thread thread = new Thread();此时线程还没有开始执行,只是一个对象。
    • 就绪(Runnable):当调用start()方法后,线程进入就绪状态。此时线程等待获取CPU资源,以便开始执行。例如,thread.start();后线程就处于就绪状态,它可能会被操作系统的调度器选中并开始执行。
    • 运行(Running):当线程获得CPU资源后,就进入运行状态,开始执行run()方法中的代码。一个时刻只有一个线程处于运行状态(在单核CPU情况下)。
    • 阻塞(Blocked):线程在等待某些条件满足时会进入阻塞状态。例如,当线程尝试获取一个被其他线程占用的锁(synchronized关键字实现的锁)时,就会进入阻塞状态,等待锁的释放。
    • 等待(Waiting):线程通过某些方法(如Object类的wait()方法)主动放弃CPU资源,进入等待状态,等待其他线程的通知。例如,在生产者 - 消费者问题中,消费者线程在队列为空时可能会调用wait()方法进入等待状态,等待生产者生产出产品后通过notify()notifyAll()方法唤醒。
    • 超时等待(Timed Waiting):与等待状态类似,但是线程会在等待一定时间后自动唤醒。例如,Thread.sleep(long millis)方法会使线程进入超时等待状态,在指定的毫秒数后自动唤醒。
    • 终止(Terminated):当线程的run()方法执行完毕或者因为异常退出时,线程就进入终止状态,此时线程生命周期结束。
  3. 如何实现线程安全?

    • 使用synchronized关键字
      • 可以修饰方法或者代码块。当修饰方法时,整个方法体在同一时刻只能被一个线程访问。例如:
        class Counter {private int count = 0;public synchronized void increment() {count++;}
        }
        
      • 当修饰代码块时,需要指定一个锁对象,只有获得这个锁对象的线程才能执行代码块。例如:
        class Counter {private int count = 0;private Object lock = new Object();public void increment() {synchronized (lock) {count++;}}
        }
        
    • 使用ReentrantLock
      • 它是java.util.concurrent.locks包中的一个可重入锁。通过lock()方法获取锁,unlock()方法释放锁。例如:
        import java.util.concurrent.locks.Lock;
        import java.util.concurrent.locks.ReentrantLock;
        class Counter {private int count = 0;private Lock lock = new ReentrantLock();public void increment() {lock.lock();try {count++;} finally {lock.unlock();}}
        }
        
    • 使用线程安全的集合类
      • 例如java.util.concurrent包中的ConcurrentHashMapCopyOnWriteArrayListCopyOnWriteArraySet等。这些集合类在设计上就考虑了多线程环境下的安全访问,通过内部的同步机制或者无锁算法来保证数据的一致性。例如,ConcurrentHashMap在高并发的读写操作下能够保证数据的正确性,而不需要像使用普通HashMap时那样额外添加同步代码。

四、JVM部分

  1. 请简单介绍一下Java虚拟机(JVM)的内存结构。
    • 程序计数器(Program Counter Register)
      • 是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。它的作用是记录当前线程执行的位置,以便在线程切换后能够恢复到正确的执行位置。它是线程私有的,每个线程都有自己独立的程序计数器。
    • Java虚拟机栈(Java Virtual Machine Stacks)
      • 也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型,每个方法在执行时都会创建一个栈帧(Stack Frame),用于存储局部变量表、操作数栈、动态连接、方法出口等信息。当一个方法被调用时,一个新的栈帧就会被压入栈中,当方法执行结束时,栈帧就会被弹出。
    • 本地方法栈(Native Method Stacks)
      • 与Java虚拟机栈类似,但是它是为本地方法(用非Java语言编写的方法,如C或C++编写的方法,通过JNI调用)服务的。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com