Java 面试266题 之 java基础

  • JAVA中的几种基本数据类型是什么,各自占用多少字节。
    参考答案1
    数据类型答案

  • String类能被继承吗,为什么。
    参考答案1
    参考答案2
    String 类是不能被继承的,因为他是被final关键字修饰的。还有一点就是String类的Immutable(不可变)属性,从上面代码也可以看出,String类实际是一个char[]数组存储数据的。而这个数组也是被final关键字修饰的。

  • String,Stringbuffer,StringBuilder的区别。
    参考答案1
    参考答案2
    基本原则
    如果要操作少量的数据,用String ;单线程操作大量数据,用StringBuilder ;多线程操作大量数据,用StringBuffer。
    StringBuffer、StringBuilder和String一样,也用来代表字符串。String类是不可变类,任何对String的改变都 会引发新的String对象的生成;StringBuffer则是可变类,任何对它所指代的字符串的改变都不会产生新的对象。

  • ArrayList和LinkedList有什么区别。
    参考答案1
    参考答案2
    ArrayList和LinkedList的区别有以下几点:
    ArrayList是实现了基于动态数组的数据结构,而LinkedList是基于链表的数据结构;
    对于随机访问get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针;
    对于添加和删除操作add和remove,一般大家都会说LinkedList要比ArrayList快,因为ArrayList要移动数据。但是实际情况并非这样,对于添加或删除,LinkedList和ArrayList并不能明确说明谁快谁慢。

  • 类的实例化顺序,比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,当new的时候,他们的执行顺序。
    参考答案1
    参考答案2
    参考答案3
    java对象实例化时的顺序为:
    父类的静态成员变量和静态代码块加载
    子类的静态成员变量和静态代码块加载
    父类成员变量和方法块加载
    父类的构造函数加载
    子类成员变量和方法块加载
    子类的构造函数加载

  • 用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。
    参考答案1
    参考答案2
    参考答案3
    并发的hashMap问题

  • JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何设计。
    参考答案1
    ConcurrentHashMap,老生常谈的分段锁,简单说起来就是,我们访问不同的key在一些操作上是可以并发的,比如改操作,(其它操作可能同时触发扩容或者hash相同碰撞覆盖等),如果直接将整个put方法锁死就会非常低效,而如果将这个散列表拆成多段,给出多个锁,这样就可以显著提高性能。

  • 有没有有顺序的Map实现类,如果有,他们是怎么保证有序的。
    参考答案1
    TreeMap和LinkedHashMap,TreeMap默认是key升序,LinkedHashmap默认是数据插入顺序。
    TreeMap实现SortMap接口,能够把它保存的记录根据键排序。
    LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的。
    默认是按键的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。

  • 抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口么。
    参考答案1
    参考答案2
    一个抽象类不能实例化。
    接口是个集合,并不是类。类描述了属性和方法,而接口只包含方法(未实现的方法)。接口和抽象类一样不能被实例化,因为不是类。但是接口可以被实现(使用 implements 关键字)。实现某个接口的类必须在类中实现该接口的全部方法。虽然接口内的方法都是抽象的(和抽象方法很像,没有实现)但是不需要abstract关键字。
    抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
    抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
    接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
    一个类只能继承一个抽象类,而一个类却可以实现多个接口。

interface Alram {
    void alarm();
}
 
abstract class Door {
    void open();
    void close();
}
 
class AlarmDoor extends Door implements Alarm {
    void oepn() {
      //....
    }
    void close() {
      //....
    }
    void alarm() {
      //....
    }
}
  • 继承和聚合的区别在哪。
    参考答案1
    参考答案2
    继承指的是一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力,继承是类与类或者接口与接口之间最常见的关系;在Java中此类关系通过关键字extends明确标识,在设计时一般没有争议性。
    聚合是关联关系的一种特例,他体现的是整体与部分、拥有的关系,即has-a的关系,此时整体与部分之间是可分离的,他们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享;比如计算机与CPU、公司与员工的关系等;表现在代码层面,和关联关系是一致的,只能从语义级别来区分。

  • IO模型有哪些,讲讲你理解的nio ,他和bio,aio的区别是啥,谈谈reactor模型。
    JAVA BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程并处理,如果这个连接不做任何事情会造成不必要的开销,当然可以通过线程池机制改善
    JAVA NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求时才启动一个线程进行处理
    JAVA AIO(NIO2):异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理
    Tomcat采用的传统的BIO(同步阻塞IO模型)+线程池模式,对于十万甚至百万连接的时候,传统BIO模型是无能为力的。
    NIO基于Reactor,当socket有流可读或可写入socket,操作系统会相应的通知引用程序进行处理,应用再将流读取到缓冲区或写入操作系统。也就是,不是一个链接就要对应一个处理线程,而是一个有效请求对应一个线程,当连接没有数据时,是没有工作线程来处理的
    Reactor模型。nio只有acceptor的服务线程是堵塞进行的,其他读写线程是通过注册事件的方式,有读写事件激活时才调用线程资源区执行,不会一直堵塞等着读写操作,Reactor的瓶颈主要在于acceptor的执行,读写事件也是在这一块分发。
    AIO需要一个链接注册读写事件和回调方法,当进行读写操作时,只须直接调用API的read或write方法即可,这两种方法均为异步,对于读操作而言,当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序;对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序
    即,read/write方法都是异步的,完成后会主动调用回调函数
    参考答案1
    参考答案2

  • 反射的原理,反射创建类实例的三种方式是什么。
    所谓的反射机制就是java语言在运行时拥有一项自观的能力。通过这种能力可以彻底的了解自身的情况为下一步的动作做准备。下面具体介绍一下java的反射机制。这里你将颠覆原来对java的理解。 Java的反射机制的实现要借助于4个类:class,Constructor,Field,Method;其中class代表的时类对 象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象。通过这四个对象我们可以粗略的看到一个类的各个组 成部分。
    通过反射机制可以获取到一个类的完整信息,例如:所有(包含private修饰)属性和方法,包信息等。
    换句话说,Class本身表示一个类的本身,通过Class可以完整获取一个类中的完整结构,包含此类中的方法定义,属性定义等。
    JavaBean是类反射的实际应用之一,它能让一些工具可视化的操作软件组件。这些工具通过类反射动态的载入并取得Java组件(类)的属性。后面学习的各种框架,基本上都会有反射的使用。
    参考答案1
    参考答案2
    参考答案3

  • 反射中,Class.forName和ClassLoader区别 。
    参考答案1
    java中class.forName和classLoader都可用来对类进行加载。前者除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。而classLoader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。Class.forName(name, initialize, loader)带参函数也可控制是否加载static块。
    Class.forName()三个参数的加载类及初始化过程同classLoader一样。
    从上边的断点调试可以看出,静态代码块不是在初始化阶段完成的,它陷于类初始化,先于普通变量默认分配(整型分配为0,字符串分配为null),这也就是为什么我们不能在静态代码块中引用普通变量的原因之一,这与上面所谓的“分配”、“初始化”相违背。

  • 描述动态代理的几种实现方式,分别说出相应的优缺点。
    参考答案1
    参考答案2
    jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。
    总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。
    AOP的拦截功能是由java中的动态代理来实现的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行。不同的切入时机对应不同的Interceptor的种类,如BeforeAdviseInterceptor,AfterAdviseInterceptor以及ThrowsAdviseInterceptor等)。
    那么动态代理是如何实现将切面逻辑(advise)织入到目标类方法中去的呢?下面我们就来详细介绍并实现AOP中用到的两种动态代理。
    AOP的源码中用到了两种动态代理来实现拦截切入功能:jdk动态代理和cglib动态代理。两种方法同时存在,各有优劣。

未完待续

  • 动态代理与cglib实现的区别。
  • 为什么CGlib方式可以对接口实现代理。
  • final的用途。
  • 写出三种单例模式实现 。
  • 如何在父类中为子类自动完成所有的hashcode和equals实现?这么做有何优劣。
  • 请结合OO设计理念,谈谈访问修饰符public、private、protected、default在应用设计中的作用。
  • 深拷贝和浅拷贝区别。
  • 数组和链表数据结构描述,各自的时间复杂度。
  • error和exception的区别,CheckedException,RuntimeException的区别。请列出5个运行时异常。
  • 在自己的代码中,如果创建一个java.lang.String类,这个类是否可以被类加载器加载?为什么。
  • 说一说你对java.lang.Object对象中hashCode和equals方法的理解。在什么场景下需要重新实现这两个方法。
  • 在jdk1.5中,引入了泛型,泛型的存在是用来解决什么问题。
  • 这样的a.hashcode() 有什么用,与a.equals(b)有什么关系。
  • 有没有可能2个不相等的对象有相同的hashcode。
  • Java中的HashSet内部是如何工作的。
  • 什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决。
  • java8的新特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值