Java 面试题整理(四)

目录

final和static的区别,static串数据问题

Java8中新增了哪些特性,这些特性有什么优点

线程的状态,以及状态之间的转换

IO和NIO的区别

HashMap,LinkedHashMap和ConcurrentHashMap的区别

session机制


final和static的区别,static串数据问题

在Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量)

1. 修饰变量,被final修饰的变量必须要初始化,赋初值后不能再重新赋值

        这个变量被初始化后便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可变,即不能再指向其他的对象

2. 修饰方法,被final修饰的方法代表不能重写

3. 修饰类,被final修饰的类,不能够被继承

static可以修饰成员变量、成员方法、代码块、内部类

1. 被static修饰的变量被是静态变量,静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。

       static成员变量的初始化顺序按照定义的顺序进行初始化。

2. 被static修饰的方法是静态方法,静态方法不依赖于任何对象就可以进行访问,对于静态方法来说,是没有this的,因为它不依附于任何对象。由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法。

3. 用static代码块以优化程序性能,可以置于类中的任何地方,类中可以有多个static块。在类被初次加载时,会按照static块的顺序来执行每一个static块,并且只会执行一次。

4. 在定义内部类的时候,可以在其前面加上一个权限修饰符static,此时这个内部类就变成了静态内部类。静态内部类不需要有指向外部类的引用,并且只能访问外部类的静态和非静态成员。

静态变量:非线程安全和串数据问题

案例(一)

/**
 * 测试静态变量的线程安全性
 * @author 75736
 *
 */
public class Demo_1 implements Runnable{

	public static int num = 50;
	
	@Override
	public void run() {
		while(num>0) {
			System.out.println(Thread.currentThread().getName() + "抢到了第" + num-- + "张票");
		}
	}
	
	public static void main(String[] args) {
		Demo_1 demo_1 = new Demo_1();
		Thread thread_1 = new Thread(demo_1);
		Thread thread_2 = new Thread(demo_1);
		Thread thread_3 = new Thread(demo_1);
		thread_1.start();
		thread_2.start();
		thread_3.start();
	}
}

案例(二)

/**
 * static串数据问题
 * @author 75736
 *
 */
public class Demo_2 implements Runnable{

	private static int a = 0;
	private static int b = 0;
	private static int c = 0;
	
	@Override
	public void run() {
		while(true) {
			System.out.println("a="+ a++ + ",b=" + b++ + ",c=" + c++);
		}
	}
	
	public static void main(String[] args) {
		Demo_2 demo_2 = new Demo_2();
		Thread thread_1 = new Thread(demo_2);
		Thread thread_2 = new Thread(demo_2);
		Thread thread_3 = new Thread(demo_2);
		thread_1.start();
		thread_2.start();
		thread_3.start();
	}
}

Java8中新增了哪些特性,这些特性有什么优点

1. Stream流,对Collection集合的改进

       Stream的出现也并不是要取代ArrayList或其他集合,它提供了一种操作大数据接口,让数据操作更容易和更快。Stream是一次性使用对象,一旦被遍历,就无法再次遍历。在遍历时,它具有过滤、映射以及减少遍历数等功能。

       distinct:对于Stream中包含的元素进行去重操作

       filter:对于Stream中包含的元素使用给定的过滤函数进行过滤操作

       map:对于Stream中包含的元素使用给定的转换函数进行转换操作

       flatMap:和map类似,不同的是其每个元素转换得到的是Stream对象,会把子Stream中的元素压缩到父集合中;

       peek:生成一个包含原Stream的所有元素的新Stream

       limit: 对一个Stream进行截断操作,获取其前N个元素,如果原Stream中包含的元素个数小于N,那就获取其所有的元素;

       skip:  返回一个丢弃原Stream的前N个元素后剩下元素组成的新Stream,如果原Stream中包含的元素个数小于N,那么返回空Stream;

       …

2. 函数式接口

什么叫函数式接口:

如果一个接口中,有且只有一个抽象的方法(Object类中的方法不包括在内),那这个接口就可以被看做是函数式接口。

Consumer/Predicate/Function/Supplier

3. Lambda

        使用它设计的代码会更加简洁。Lambda表达式是对象,它们必须依附于一类特别的对象类型——函数式接口(Functional Interface)。

4. Optional

        主要作用就是解决Java中的NPE(NullPointerException)。空指针异常在程序运行中出现的频率非常大,我们经常遇到需要在逻辑处理前判断一个对象是否为null的情况。

       创建Optional实例:of()、ofNullable()

       访问Optional对象的值(取回实际值对象):get()

       返回默认值:orElse()、orElseGet()

5. Java time

java.time包来清理各种时间接口。所有类都是不可变的、线程安全的。

        LocalDate 时间

        LocalTime 日期

        LocalDateTime 时间和日期

       DateTimeFormatter 格式化时间

线程的状态,以及状态之间的转换

参考至: 线程五种状态 - coderDu - 博客园

线程的5种状态

public enum State {
    
    NEW,

    RUNNABLE,

    BLOCKED,

    WAITING,

    TIMED_WAITING,

    TERMINATED;
}

1. 新建new:创建后但是尚未启动的线程

2. 运行runnable:包括系统的running和ready状态,也就是此状态线程可能在执行,也可能在等待cpu为其分配执行时间

3. 无限等待waiting:释放锁更不会分配cpu时间,等待持有同一锁对象的线程(或者Condition对象)唤醒

4. 限期等待timed awaiting:不分配cpu时间,但无需被其他线程显示的唤醒,一定时间后自动唤醒。

5. 阻塞blocked:与等待的区别是,他在等待获取一个排他锁,比如方法调用另一个synchronized方法,但是另一个线程却持有锁对象

6. 结束terminate:结束执行run方法

状态转换图

IO和NIO的区别

参考至: Java IO 和 NIO的区别_大鹏小站的博客-CSDN博客_io和nio

1. 主要区别

IO

NIO

面向字节流

面向缓冲区

阻塞

基于Selector的非阻塞

2. 面向流和面向缓冲区

        在Java IO中读取数据和写入数据是面向流(Stream)的,这表示当我们从流中读取数据,写入数据时也将其写入流,流的含义在于没有缓存

        在Java NIO中数据的读写是面向缓冲区(Buffer)的,读取时可以将整块的数据读取到缓冲区中,在写入时则可以将整个缓冲区中的数据一起写入。

3. 阻塞和非阻塞

        Java IO是阻塞的,如果在一次读写数据调用时数据还没有准备好,或者目前不可写,那么读写操作就会被阻塞直到数据准备好或目标可写为止

        Java NIO则是非阻塞的,每一次数据读写调用都会立即返回,并将目前可读(或可写)的内容写入缓冲区或者从缓冲区中输出,即使当前没有可用数据,调用仍然会立即返回并且不对缓冲区做任何操作。

HashMap,LinkedHashMap和ConcurrentHashMap的区别

1. HashMap

       线程不安全,允许null作为key和value 

       无序:迭代HashMap的顺序并不是HashMap放置的顺序

       JDK7:底层维护一个数组,数组中的每一项都是一个Entry,数组+链表结构

       JDK8:链表+红黑树

2. ConcurrentHashMap

       JDK7:使用了锁分段技术技术来保证线程安全的,锁分段技术:首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问;

       JDK8:取消了基于 Segment 的分段锁思想,改用 CAS + synchronized 控制并发操作,在某些方面提升了性能。并且追随 1.8 版本的 HashMap 底层实现,使用数组+链表+红黑树进行数据存储

3. LinkedHashMap

       线程不安全,允许null作为key和value。

       哈希表+链表:继承自HashMap,实现了Map<K,V>接口,其内部还维护了一个双向链表。

       有序:增加时间和空间上的开销,通过维护一个运行于所有条目的双向链表,保证了元素迭代的顺序

session机制

参考至: https://justsee.iteye.com/blog/1570652

session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构来保存信息。

        当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。

        保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发给服务器。一般这个cookie的名字都是类似于JSEEESIONID。

        由于cookie可以被人为的禁止,必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面,附加方式也有两种,一种是作为URL路径的附加信息,另一种技术叫做表单隐藏字段。

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值