Java面试题=>基础部分(1)

Java面试题基础篇


八种基本数据类型的大小、默认值以及他们的封装类
基本类型大小(字节)默认值封装类取值范围
byte10Byte-27至27-1
short20Short-215至215-1
int40Integer-231至231-1
long80LLong-263至263-1
float40.0fFloat
double80.0dDouble
boolean-falseBoolean
char2\u0000Character

布尔类型所占字节大小有以下三种说法:

  1. 1个bit
    boolean类型的值只有true和false两种逻辑值,在编译后会使用1和0来表示,这两个数在内存中只需要1位(bit)即可存储,位是计算机最小的存储单位。
  2. 1个字节
    虽然编译后1和0只需占用1位空间,但计算机处理数据的最小单位是1个字节,1个字节等于8位,实际存储的空间是:用1个字节的最低位存储,其他7位用0填补,如果值是true的话则存储的二进制为:0000 0001,如果是false的话则存储的二进制为:0000 0000。
  3. 4个字节
    来源是《Java虚拟机规范》一书中的描述:“虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操作的boolean值,在编译之后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每个元素boolean元素占8位”。这样我们可以得出boolean类型占了单独使用是4个字节,在数组中又是1个字节。

总结:很显然第三种说法是更准确的,由此可得出如果使用boolean类型声明一个变量的话,一个boolean占四个字节,如果使用boolean声明一个数组类型,那么数组的每个元素占一个字节。

switch中能否使用String做参数

在JDK7之前,switch只支持byte,short,char,int或是其对应的包装类及Enum类型,从JDK1.7开始switch就支持了String做参数。
ps:jdk1.7并没有新的指令来处理switch string,而是通过调用switch中string.hashCode,将string转换为int从而进行判断。

equals与==的区别
  • 对于基本数据类型,使用“=="比较值是否相等。
  • 对于引用数据类型,使用equals()和“==”效果是一样的,两者比较的都是对象在内存中的存放地址(确切的说,是堆内存地址)
  • 对于String、Integer、Date等覆盖了equals()方法的类型,“==”比较的是存放的内存地址。而equals()的结果则由覆盖后的代码决定。
Object类有哪些公用方法

Object是所有类的父类,任何类都默认继承Object。

  • clone 保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则会抛出CloneNotSupportedException异常。
  • equals 在Object中与==是一样的效果,子类一般需要重写该方法,例如String类。
  • hashCode 该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
  • getClass final方法,获得运行时类型。
  • wait 使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。 wait() 方法一直等待,直到获得锁或者被中断。 wait(long timeout) 设定一个超时间隔,如果在规定时间内没有获得锁就返回。调用该方法后当前线程进入睡眠状态,直到以下事件发生1、其他线程调用了该对象的notify方法。 2、其他线程调用了该对象的notifyAll方法。 3、其他线程调用了interrupt中断该线程。 4、时间间隔到了。 5、此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。
  • notify 唤醒在该对象上等待的某个线程。
  • notifyAll 唤醒在该对象上等待的所有线程。
  • toString 转成字符串,一般子类都有重写,否则打印句柄。
Java的四种引用,强弱软虚,用到的场景
  • 强引用
    最最普通的一种引用方式,比如String name = "Tony",变量name就是字符串"Tony"的强引用,只要强引用存在,垃圾回收期就不会回收这个对象。
  • 软引用
    用于描述还有用,但是非必须的对象,如果内存足够,不回收,如果内存不足,则会被回收。一般用于实现内存敏感的高速缓存,软引用可以和引用队列ReferenceQueue联合使用,如果软引用的对象被垃圾回收,JVM就会把这个软引用加入到与之关联的引用队列中。
  • 弱引用
    弱引用和软引用大致相同,弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。
  • 虚引用
    就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。 虚引用主要用来跟踪对象被垃圾回收器回收的活动。
ArrayList、LinkedList、Vector的区别

List的三个子类的特点:
ArrayList

  • 底层结构是数组,查询快,增删慢。
  • 底层线程不安全,效率高。

Vector

  • 底层结构是数组,查询快,增删慢。
  • 线程安全,效率低。
  • Vector相对ArrayList查询慢(线程安全的)
  • Vector相对LinkedList增删慢(数组结构)

LinkedList

  • 底层数据结构是链表,查询慢,增删快。
  • 线程不安全,效率高。

Vector和ArrayList的区别

  • Vector是线程安全的,效率低。
  • ArrayList是线程不安全的,效率高。
  • 共同点:底层数据结构都是数组实现的,查询快,增删慢。

ArrayList和LinkedList的区别

  • ArrayList底层是数组结构,查询和修改快。
  • LinkedList底层是链表结构,增删快,查询和修改比较慢。
  • 共同点:都是线程不安全的。

List有三个子类使用

  • 查询多,用ArrayList。
  • 增删多,用LinkedList。
  • 如果查询和增删都多那就用ArrayList。
String、StringBuffer、StringBuilder的区别

String:适用于少量的字符串操作情况。
StringBuilder:适用于“单线程”下在字符缓冲区进行大量操作的情况。
StringBuffer:适用于“多线程”下在字符缓冲区进行大量操作的情况。
StringBuilder是线程不安全的,而StringBuffer是线程安全的。
这三个类的区别主要在于两个方面,运行速度和线程安全方面的区别。首先说运行速度,StringBuilder > StringBuffer > String。

因为String是字符串常量,而StringBuffer和StringBuilder都是字符串变量,String对象一旦创建是不可以修改的,但StringBuffer和StringBuilder都是变量是可以修改的,所以String是三者中最慢的。

在线程安全上,StringBuiler是线程不安全的,StringBuffer反之,如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法带有synchronized,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作,所以如果要进行的操作是多线程的,那就用StringBuffer,如果是在单线程的情况下,还是建议使用速度更快的StringBuilder。

接口和抽象类的区别
比较抽象类接口
默认方法抽象类可以有默认的实现JDK1.8之前,接口中不存在方法的实现
实现方法子类使用extends关键字来继承抽象类,如果子类不是抽象类,子类需要实现抽象类中所有的抽象方法子类使用implements实现接口,需要提供接口中所有声明的实现
构造器抽象类中可以有构造器接口中不能有构造器
和正常类的区别抽象类不能被实例化接口是完全不同的类型
访问修饰符抽象方法可以有public、protected和default等修饰接口默认是public,不能使用其他访问修饰符
多继承一个子类只能存在一个父类一个类可以实现多个接口
添加新方法向抽象类中添加新方法,可以提供默认的实现,因此可以不必修改子类现有的实现如果往接口中添加新方法,则子类中必须实现该方法
面向对象的三大特征
  1. 封装
    封装符合面向对象设计原则的第一条:单一性原则,一个类把自己该做的事情封装起来,而不是暴露给其他类去处理,当内部的逻辑发生变化时,外部调用不用因此而修改,他们只调用开放的接口,而不用去关心内部的实现
  2. 继承
    继承是类与类的一种关系,是一种“is a”的关系。比如“狗”继承“动物”,这里动物类是狗类的父类或者基类,狗类是动物类的子类或者派生类。子类拥有父类的所有属性和方法(除了private修饰的属性不能拥有)从而实现了实现代码的复用
  3. 多态
    Java中的多态是建立在继承的基础之上的,多态是同一个行为具有多个不同表现形式或形态的能力。比如说“宠物”这个对象,它就有很多不同的表达或实现,有小猫,小狗等等,我们到宠物店去跟服务员说“我要一只宠物”,那么服务员给我小猫,小狗都可以,因为他们都是宠物,所以我们就说“宠物”这个对象具有多态性。
Java程序设计六大原则
单一职责

指一个类的功能要单一,不能包罗万象,高内聚,低耦合。

开闭原则

指一个模块在扩展性方面应该是开放的,在更改性方面应该是关闭的。为达到目的需要对系统进行抽象化设计(关键)。

替换原则

子类应当可以替换父类,并可以出现在父类能够出现的任何位置。

依赖原则

具体依赖抽象,上层依赖下层

接口分离原则

模块间要通过抽象接口隔开,而不是通过具体的类强耦合起来。

迪米特原则

一个对象应当尽可能少的去了解其他对象,尽可能的做到“老死不相往来”,核心就是两个类/两个系统之间知道的东西越少越好!狭义的迪米特法则中也有相关的概念——调用转发,尽量使用一个第三者的朋友来进行通信如果必须要通信的话。

以上原则都是为了一个目的——“高内聚,低耦合”
Java中有没有GOTO

Java中的保留字,目前还没有在Java中使用。

has-a与is-a的区别

is-a表示的是属于的关系。比如小狗属于一种动物(继承关系)。
has-a表示组合,包含关系。比如小狗包含有牙齿,舌头等组件。

ClassLoader如何加载class

JVM里有多个类加载器,每个类加载器可以负责加载特定位置的类,例如,bootstrap类加载负责加载jre/lib/rt.jar中的类,我们平时用的jdk中的类都位于rt.jar中。extclassloader负责加载jar/lib/ext/*.jar中的类,appclassloader负责classpath指定的目录或jar中的类。除了bootstrap之外,其他的类加载器本身也都是java类,它们的父类是ClassLoader。

hashCode方法的作用

hashcode这个方法是用来鉴定2个对象是否相等的。
equals方法和hashCode方法这2个方法都是用来判断2个对象是否相等的,但是他们是有区别的。

一般来讲,equals这个方法是给用户调用的,如果你想判断2个对象是否相等,你可以重写equals方法,然后在代码中调用,就可以判断他们是否相等了。简单来讲,equals方法主要是用来判断从表面上看或者从内容上看,2个对象是不是相等。举个例子,有个学生类,属性只有姓名和性别,那么我们可以认为只要姓名和性别相等,那么就说这2个对象是相等的。

hashcode方法一般用户不会去调用,比如在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就判断了hashcode这个方法,而且也用到了equals方法。这里不可以重复是说equals和hashcode只要有一个不等就可以了!所以简单来讲,hashcode相当于是一个对象的编码,就好像文件中的md5,他和equals不同就在于他返回的是int型的,比较起来不直观。我们一般在覆盖equals的同时也要覆盖hashcode,让他们的逻辑一致。举个例子,还是刚刚的例子,如果姓名和性别相等就算2个对象相等的话,那么hashcode的方法也要返回姓名的hashcode值加上性别的hashcode值,这样从逻辑上,他们就一致了。

要从物理上判断2个对象是否相等,用==就可以了,如果两个对象的物理(内存)地址相等,那么这两个对象肯定就是同一个对象。

Java中堆和栈有什么不同

每个线程都有自己的栈内存,用于存储本地变量,方法参数和栈调用,一个线程中存储的变量对其他线程是不可见的。而堆是所有线程共享的一片内存区域。对象都是在堆里面创建,为了提升效率会从堆中弄一个缓存到自己的栈。

堆:(对象)
引用类型的变量,其内存分配在堆上或者常量池(字符串常量、基本数据类型常量),需要通过new等方式来创建。
堆内存主要作用是存放运行时创建(new)的对象。

栈:(基本数据类型变量、对象的引用变量)
基本数据类型的变量以及对象的引用变量,其内存分配在栈上,变量出了作用域就会自动释放。

线程安全是什么?线程不安全是什么?

就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问。
什么叫线程安全:
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的,反之就是线程不安全的。
线程安全问题都是由全局变量及静态变量引起的,若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值