Java面经(基础版)

1.Java的优势?

简答

跨平台、提供垃圾自动回收功能、生态圈丰富

扩展

  • Java是跨平台的,不同平台执行的机器码是不一样的,而Java因为加了一层中间层,所以可以做到一次编写多平台运行,即Write once,Run anywhere。
  • Java提供垃圾自动回收功能,在内存较充裕的当下,将内存的管理交给GC来做,减轻了程序员编程的负担,提升了开发效率。(手动管理内存意味着自由、精细化地掌控,但是很容易出错。)
  • Java生态圈非常丰富,有丰富的第三方类库、网上全面的资料、企业级框架、各种中间件等。

2.JDK1.8(Java 8)的新特性

简答

  • 用元空间代替了永久代
  • 引入了Lambda表达式
  • 引入了日期类、接口默认方法、静态方法
  • 新增Stream流式接口
  • 引入了Optional类
  • 新增了CompletableFeture、StampedLock等并发实现类
  • 修改了HashMap、ConcurrentHashMap的实现

扩展

1.Lambda表达式

Lambda 是Java 8引入的一种匿名函数,可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码,其本质是作为函数式接口的实例,示例如下:

// 传统方式
Runnable runnable1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("mianshiya.com");
    }
};

// Lambda 表达式
Runnable runnable2 = () -> System.out.println("mianshiya.com");

2.日期类

Java 8引入了新的日期和时间API(位于java.time包中),它们更加简洁和易于使用,解决了旧版日期时间API的许多问题。
例如Date ,Calendar都是可变类且线程不安全。而新的日期类都是不可变的,一旦创建就不能修改,这样可以避免意外的修改,提升代码的安全性和可维护性。

interface MyInterface {
    default void defaultMethod() {
        System.out.println("Default Method");
    }

    static void hello() { 
        System.out.println("Hello, New Static Method Here"); 
    } 
}

Date本身不包含时区信息,必须使用Calendar类来处理时区,但使用起来非常复杂且容易出错。
新API提供了专门的时区类(如ZonedateTime ,OffsetDateTime,ZoneId等),简化了时区处理,并且这些类的方法更加直观和易用。

3.接口默认方法、静态方法

默认方法允许在接口中定义方法的默认实现,这样接口的实现类不需要再实现这些方法。之所以提供静态方法,是为了将相关的方法内聚在接口中,而不必创建新的对象。示例如下:

interface MyInterface {
    default void defaultMethod() {
        System.out.println("Default Method");
    }

    static void hello() { 
        System.out.println("Hello, New Static Method Here"); 
    } 
}

4.Stream流式接口

Stream API提供了一种高效且易于使用的方式来处理数据集合。它支持链式操作、惰性求值和并行处理。示例如下:

List<String> list = Arrays.asList("a", "b", "c", "d");
List<String> result = list.stream()
                          .filter(s -> s.startsWith("a"))
                          .collect(Collectors.toList());

5.Optional类

Optional类是Java 8引入的一个容器类,它用来表示一个值可能存在或不存在。

Optional可以给返回结果提供了一个表示无结果的值,而不是返回null(网上比较流行的说法是Optional可以避免空指针,其实不是很准确)。常用方式如下:

Optional<User> userOption = Optional.ofNullable(userService.getUser(...));
if (!userOption.isPresent()) {....}

Optional类用来解决可能出现的NullPointerException问题,提供了一种优雅的方式来处理可能为空的值。

使用Optional的好处
可以简化平日里一系列判断null的操作,使得用起来的时候看着不需要判断null,不需要担心出现空指针的情况(该有的判断Optional替我们完成了)。

如下是使用与不使用Optional类的代码对比:

//没有使用Optional
Yes yes = getYes();
if (yes != null) {
    Address yesAddress = yes.getAddress();
    if (yesAddress != null) {
        Province province = yesAddress.getProvince();
        System.out.println(province.getName());
    }
}
throw new NoSuchElementException(); //如果没找到就抛错
//使用Optional
Optional.ofNullable(getYes())
        .map(a -> a.getAddress())
        .map(p -> p.getProvince())
        .map(n -> n.getName())
        .orElseThrow(NoSuchElementException::new);

如果用了Optional,代码里不需要判空的操作,即使address、province为空的话,也不会产生空指针错误。

6.CompletableFuture

CompletableFuture提供了一个新的异步编程模型,简化了异步任务的编写和管理。

CompletableFuture.supplyAsync(() -> "Hello")
                 .thenApply(s -> s + " World")
                 .thenAccept(System.out::println);

7.StampedLock

StampedLock可以认为是读写锁的“改进“版本。
读写锁读写是互斥的,而StampedLock搞了个悲观读和乐观读,悲观读和写是互斥的,乐观读则不会。官方示例代码如下:

 class Point {
   private double x, y;
   private final StampedLock sl = new StampedLock();

   void move(double deltaX, double deltaY) { // an exclusively locked method
     long stamp = sl.writeLock();  //获取写锁
     try {
       x += deltaX;
       y += deltaY;
     } finally {
       sl.unlockWrite(stamp); //释放写锁
     }
   }

   double distanceFromOrigin() { // A read-only method
     long stamp = sl.tryOptimisticRead(); //乐观读
     double currentX = x, currentY = y;
     if (!sl.validate(stamp)) { //判断共享变量是否已经被其他线程写过
        stamp = sl.readLock();  //如果被写过则升级为悲观读锁
        try {
          currentX = x;
          currentY = y;
        } finally {
           sl.unlockRead(stamp); //释放悲观读锁
        }
     }
     return Math.sqrt(currentX * currentX + currentY * currentY);
   }

   void moveIfAtOrigin(double newX, double newY) { // upgrade
     // Could instead start with optimistic, not read mode
     long stamp = sl.readLock(); //获取读锁
     try {
       while (x == 0.0 && y == 0.0) {
         long ws = sl.tryConvertToWriteLock(stamp);  //升级为写锁
         if (ws != 0L) {
           stamp = ws;
           x = newX;
           y = newY;
           break;
         }
         else {
           sl.unlockRead(stamp);
           stamp = sl.writeLock();
         }
       }
     } finally {
       sl.unlock(stamp);
     }
   }
 }

乐观锁就是获取判断—下,如果被修改了那么就升级为悲观锁。
但是StampedLock是不可重入锁,而且也不支持condition。并且如果线程使用writeLock()或者readLock()获得锁之后,线程还没执行完就被interrupt()的话,会导致CPU飙升,需要用
readLockInterruptibly或者writeLockInterruptibly 。

8.HashMap

9.ConcurrentHashMap
 

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值