前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

(2020 )Java最新面试笔试题答案解析(一)

qiguaw 2024-10-10 08:18:00 资源文章 16 ℃ 0 评论

Java中的集中基本数据类型是什么?各占用多少字节?


【数值型】—(整数类型) byte(1字节) short(2字节) int(4字节) long(8字节)

拓展:Java中的数据类型除了上面的基本类型,还有一种【引用数据类型

  • 类(class)
  • 接口(interface)
  • 数组([])

对位(bit)和字节(byte)的解析:

  • bit 位:位是计算机中存储数据的最小单位,指二进制数中的一个位数,其值为“0”或“1”。
  • byte 字节:字节是计算机存储容量的基本单位,一个字节由8位二进制数组成。在计算机内部,一个字节可以表示一个数据,也可以表示一个英文字母,两个字节可以表示一个汉字。

基本单位换算:

  • 1B=8bit
  • 1Byte=8bit(1字节等于8位)
  • 1KB=1024Byte(字节)=8*1024bit
  • 1MB=1024KB
  • 1GB=1024MB
  • 1TB=1024GB

List、Map、Set三个接口,存取元素时,各有什么特点?

Java容器分为Collection和Map两大类,Collection集合的子接口有Set、List、Queue三种。工作中常用的是Set、List两种子接口。

注意:Map不是Collection的子接口。

  • List:有序容器(元素存入集合的顺序和元素从集合中取出时的顺序一致);集合内元素可重复;可插入多个null元素;元素都有索引。【常用实现类:ArrayList、LinkedList、Vector】
  • Set:无序容器(元素存入集合的顺序和元素从集合中取出时的顺序可能不一致);集合内元素不可重复[必须保证元素的唯一性];只允许存入一个null元素。【常用实现类:HashSet、LinkedHashSet、TreeSet】
  • Map:键值对(key-value)集合(存储键、值以及两者之间的映射);键(key) 无序,且唯一;值(value)不要求有序,且允许重复。【常用实现类:HashMap、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap】

拓展:集合框架底层数据结构

Collection

List集合:

ArrayList、Vector: Object数组

LinkedList:双向循环链表

Set集合:

HashSet(无序,唯一):基于 HashMap 实现的,底层采用 HashMap 来保存元素

LinkedHashSet: LinkedHashSet 继承与 HashSet,并且其内部是通过 LinkedHashMap 来实现的

TreeSet(有序,唯一): 红黑树(自平衡的排序二叉树)

Map

HashMap:JDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突);JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为【红黑树】,以减少搜索时间

LinkedHashMap:继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑

HashTable:数组+链表组成的,数组是 HashMap 的主体链表则是主要为了解决哈希冲突而存在的

TreeMap: 红黑树(自平衡的排序二叉树)

集合之线程安全

  • Vector:相比ArrayList多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
  • statck:堆栈类,先进后出。
  • HashTable:相比HashMap 多了个线程安全。
  • enumeration:枚举,相当于迭代器。

介绍一下Spring IOC 和 AOP 的理解,以及 Spring 的注入方式?

Spring 中的 IOC 的实现原理就是工厂模式加反射机制。

IOC ( Inversion of Control 控制反转):传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。

Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。

DI(Dependency Injection 依赖注入):由 IOC 容器动态的将某个对象所需要的外部资源(包括对象、资源、常量数据)注入到组件( spring 中的组件如:controller, service..等)之中。[即是 IOC 会把你当前对象所需要的外部资源动态的注入给你]

例如:在 UserAction 中要用到 UserServiceImpl 中的方法,最初的方法是在 UserAction 中通过

UserService userService = new UserServiceImpl; 需要它的时候就 new 出来,控制权在自己手里,

但是使用 Spring 后,UserAction 不用主动去创建 UserServiceImpl 的实例了,

这个工作已经交给 Spring来做了。然后 你要用的时候再直接问 Spring 要,就可以拿来用了。

这个时候你就由原来的主动创建,变成了被动依赖 Spring 创建好之后给你的注入,才能使用。

控制权已经反转给 Spring 了~

AOP (Aspect-Oriented Programming 面向切面编程):在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程

比如说 声明式事务管理的时候,我们在 service 层检测到save*、update*这些方法要被调用的时候,我们先进行开启事务,这就是AOP,面向编程的思想。


依赖注入(DI)是时下最流行的IOC 实现方式:Setter方法注入(Setter Injection)、构造器注入(Constructor Injection)、基于注解的注入、【接口注入(Interface Injection)由于在灵活性和易用性比较差,从Spring4开始已被废弃】

构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。

Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。

构造器依赖注入和 Setter方法注入的区别:

两种依赖方式都可以使用,构造器注入和Setter方法注入。最好的解决方案是用构造器参数实现强制依赖,setter方法实现可选依赖。


手写一个单例模式(Singleton)以下任意一种皆可

饿汉式—静态常量方式(线程安全):类加载时就初始化实例,避免了多线程同步问题。天然线程安全。

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}

饿汉式—静态代码块方式(线程安全):将类的实例化放在了静态代码块中,其他同静态常量方式无区别

public class Singleton {
    private static Singleton instance;
    static {
        instance = new Singleton();
    }
    private Singleton() {}
    public static Singleton getInstance() {
        return instance;
    }
}

懒汉式(线程不安全):这是最基本的实现方式,第一次调用才初始化,实现了懒加载的特性。多线程场景下禁止使用,因为可能会产生多个对象导致不再是单例。

public class Singleton {
    private static Singleton singleton;
    private Singleton() {}
    public static Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

懒汉式(线程安全,方法上加同步锁:保证了多线程场景下的单例,效率会有所折损

public class Singleton {
    private static Singleton singleton;
    private Singleton() {}
    public static synchronized Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

双重校验锁(线程安全,效率高):不用每次需要获得锁,减少了获取锁和等待的时间
注意volatile关键字的使用,保证了各线程对singleton静态实例域修改的可见性。

public class Singleton {
	private volatile static Singleton singleton;
	private Singleton() {}
	public static Singleton getSingleton() {
		if (singleton == null) {
			synchronized (Singleton.class) {
				if (singleton == null) {
						singleton = new Singleton();
				}
			}
		}
		return singleton;
	}
}

静态内部类实现单例(线程安全、效率高):这种方式下 Singleton 类被装载了,instance 不一定被初始化。因为 SingletonHolder 类没有被主动使用,只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。
注意内部类SingletonHolder要用static修饰且其中的静态变量INSTANCE必须是final的。

public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表