一、Java基础
(1)面向对象编程的四大特性及其含义?
- 封装:封装就是把过程和数据包裹起来,对数据的访问只能通过特定的界面.如私有变量,用set,get方法获取。封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的变动影响。
- 继承:子类继承父类,不仅可以有父类原有的方法和属性,也可以增加自己的或者重写父类的方法及属性,这是类之间的一种关系,提高了软件的可重用性和可扩展性。
- 抽象:忽略一个主题中与当前目标无关的东西,专注的注意与当前目标有关的方面。抽象并不打算了解全部问题,而是选择其中的一部分,暂时不用部分细节。
- 多态:允许不同类的对象对同一消息作出响应。
(2)String、StringBuffer和StringBuilder的区别?String 有没有length()方法?数组有没有length()方法?
- String是字符串常量:即String对象创建后不可更改,因此在每次对String类型进行改变的时候其实都等于生成了一个新的String对象。
- StringBuffer是字符串变量:线程安全的,这是由于StringBuffer对方法加了同步锁或者对调用的方法加了同步锁。每次改变结果都会对StringBuffer对象本身进行操作,而不是生成新的对象。
- StringBuilder是字符串变量:非线程安全的,没有锁,高效。
- String更适用于少量的字符串操作的情况,StringBuilder适用于单线程下在字符缓冲区进行大量操作的情况,StringBuffer适用于多线程下在字符缓冲区进行大量操作的情况
- String中有length()方法
- 数组没有length()方法,有length的属性
(3)String a = ""和String a = new String("")的关系和异同?
- 通过String a = ""直接赋值的方式得到的是一个字符串常量,存在于常量池;注意,相同内容的字符串在常量池中只有一个,即如果池已包含内容相等的字符串会返回池中的字符串,反之会将该字符串放入池中。
- 通过new String("")创建的字符串不是常量是实例对象,会在堆内存开辟空间并存放数据,且每个实例对象都有自己的地址空间
(4)Object的equal()和==的区别?
- equals:操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。
- ==:对于基本数据类型来说,操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
(5)Java四类八种数据类型,char型变量中能不能存储一个中文汉字?为什么?
- 整型:byte占用字节1、short占用字节2、int占用字节4 、long占用字节8
- 浮点型:float占用字节4、double占用字节8
- 字符型:char占用字节2
- 布尔型:boolean
- 包装类型:Byte,Short,Integer,Long,Float,Double,Character,Boolean,
- char类型可以存储一个中文汉字。因为Java中使用的编码是Unicode,一个char类型占两个字节,所以放一个中文是没有问题的。
**(6)装箱、拆箱什么含义?
- 装箱就是自动将基本数据类型转换为包装器类型。
- 拆箱就是自动将包装器类型转换为基本数据类型。
(7)int和Integer的区别?
- Integer是int的包装类,int则是java的一种基本数据类型
- Integer变量必须实例化后才能使用,而int变量不需要
- Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
- Integer的默认值是null,int的默认值是0
(8)float f = 3.4;是否正确?
- 不正确。java中小数默认为double类型的,双精度数赋值给浮点型属于向下转型会造成精度丢失,因此需要强制类型转换float f = (float)3.4或float f = 3.4f。
(9)short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗?
- 1是int类型的,因此s1 + 1运算结果也是int类型的,所以需要强制转换类型才能赋值给short。
- s1 += 1;能够正常编译,因为其中有隐含的类型强制转化。
(10)final、finally、finalize分别表示什么含义
- final关键字表示不可更改,final修饰的变量必须要初始化,且赋初值后不能再重新赋值;final修饰的方法不能被子类重写;final修饰的类不能被继承。
- finally:和try、catch成套使用进行异常处理,无论是否捕获或处理异常,finally块里的语句都会被执行,特殊情况下,finally块才不会被执行。
- finalize():是Object中的方法,当垃圾回收器将回收对象从内存中清除出去之前会调用finalize(),但此时并不代表该回收对象被回收。
**(11)抽象类和接口的异同?
- 使用上的区别:一个类只能继承一个抽象类却可以实现多个接口
- 设计上的区别:接口是对行为的抽象,无需有子类的前提,是自上而下的设计理念;抽象类是对类的抽象,建立于相似子类之上,是自下而上的设计理念
(12)Object有哪些公有方法?
- equals(): 和==作用相似
- hashCode():用于哈希查找,重写了equals()一般都要重写该方法
- getClass(): 获取Class对象
- wait():让当前线程进入等待状态,并释放它所持有的锁
- notify()¬ifyAll(): 唤醒一个(所有)正处于等待状态的线程
- toString():转换成字符串
(13)Java中引用有几种类型?在Android中常用于什么情景?
- 强引用(StrongReference):具有强引用的对象不会被GC;即便内存空间不足,JVM宁愿抛出OutOfMemoryError使程序异常终止,也不会随意回收具有强引用的对象。
- 软引用(SoftReference):只具有软引用的对象,会在内存空间不足的时候被GC;软引用常用来实现内存敏感的高速缓存。
- 弱引用(WeakReference):只被弱引用关联的对象,无论当前内存是否足够都会被GC;常用于解决内存泄漏的问题
- 虚引用(PhantomReference):仅持有虚引用的对象,在任何时候都可能被GC;常用于跟踪对象被GC回收的活动;必须和引用队列 (ReferenceQueue)联合使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
(14)什么是内部类?有什么作用?静态内部类和非静态内部类的区别?
- 内部类就是定义在另外一个类里面的类。它隐藏在外部类中,封装性更强,不允许除外部类外的其他类访问它;但它可直接访问外部类的成员。
- 静态内部类是指被声明为static的内部类,可不依赖外部类实例化;而非静态内部类需要通过生成外部类来间接生成。
- 静态内部类只能访问外部类的静态成员变量和静态方法,而非静态内部类由于持有对外部类的引用,可以访问外部类的所用成员
(15)为什么匿名内部类中使用局部变量要用final修饰?
- 方法中的局部变量的生命周期很短,一旦方法结束变量就要被销毁,为了保证在内部类中能找到外部局部变量,通过final关键字可得到一个外部变量的引用;
- 通过final关键字修饰就不会在内部类去做修改该变量的值,保护了数据的一致性。
(16)重写(override)和重载(overload)的区别?构造器(constructor)是否可被重写(override)?
- 重写:父类与子类之间的多态性,对父类的函数进行重新定义。表示子类重写父类的方法;
- 重载:重载是让类以统一的方式处理不同类型数据的一种手段。表示有多个同名函数同时存在,区别在于有不同的参数个数或类型
- 构造器能够被重载,不能被重写。
(17)线程/工作内存/主内存之间关系?
- 每个线程都有一个独立的工作内存,用于存储线程私有的数据。
- Java内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问。
- 线程对变量的操作(读取赋值等)必须在工作内存中进行。
(18)主内存和工作内存之间关系?
- 主内存是在运行期间所有变量的存放区域,工作内存是运行期间中某一线程独立私有的内存存放区域。
- 线程间无法访问对方的工作内存空间,都是通过主内存交换来实现。
- 主内存的变量在工作内存中的值是复制过去的副本,读写完成后刷新主内存,这意味着主内存如果发生了改变,工作内存并无法获得最新的结果。
- 多个线程对一个共享变量进行修改时,都是对自己工作内存的副本进行操作,相互不可见。主内存最后得到的结果是不可预知的
(19)在Java内存模型有哪些可以保证并发过程的原子性、可见性、有序性的措施?
- 保证内存模型原子性可以通过lock和synchronized。
- 保证内存模型可见性可以通过final、volatile、synchronized。
- 保证内存模型可见性可以通过volatile和synchronized。
(20)Java中堆和栈的区别?
- 栈内存存储的是局部变量而堆内存存储的是实体;
- 栈中的数据都是私有的而堆中的数据被所有线程共享;
- 栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;
- 栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的
(21)&与&&的区别?最有效的方法计算2乘以8?
- &按位与:对每一个都判断
- &&短路与:只要前面是false就输出false,而不继续判断后面了
- 2 << 3;
(22)Math函数方法
- Math.abs() 求绝对值
- Math.sin() 正弦函数
- Math.cos()余弦函数
- Math.round()四舍五入
- Math.ceil()得到不小于某数的最小整数
- Math.floor()得到不大于某数的最大整数
(23)try{}里面一个return语句,那么finally{}里的代码会不会被执行,什么时候被执行?
- 会执行
- 在执行return后执行
**(24)swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
- 早期的JDK中可以使用byte,从1.7开始加入String,long是不可以的。
(25)静态与非静态的区别
- 静态变量被所有的对象所共享,在内存中只有一个副本;非静态变量是对象所拥有的,存在多个副本,各个对象拥有的副本互不影响。
- 静态方法中不能访问类中的非静态成员变量和非静态成员方法,静态方法中不能使用this关键字,静态方法无法被重写;在非静态成员方法中是可以访问静态成员方法和变量的
- 静态类不能实例化只能存在静态成员。非静态类中可以存在静态成员方法和变量。
- 内部静态类不需要有指向外部类的引用。但非静态内部类需要持有对外部类的引用。
- 非静态内部类能够访问外部类的静态和非静态成员。静态内部类不能访问外部类的非静态成员。他只能访问外部类的静态成员。
(26)当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
- 是值传递。Java 编程语言只有值传递参数。
(27)抽象类(abstract class)和接口(interface)有什么异同?
不同点
- 抽象类中可以定义构造器;接口中不能定义构造器;
- 抽象类中可以有抽象方法和具体方法;接口中方法全部都是抽象方法;
- 抽象类中的成员可以是 private、默认、 protected、 public;接口中的成员全都是public的;
- 抽象类中可以定义成员变量,接口中定义的成员变量实际上都是常量;
- 抽象类中可以包含静态方法;接口中不能有静态方法;
- 一个类只能继承一个抽象类,可以实现多个接口;
- 有抽象方法的类必须被声明为抽象,而抽象类未必要有抽象方法;
相同点
- 都不能被实例化
- 可以将抽象类和接口类型作为引用类型
- 接口的实现类或抽象类的子类都必须实现了接口或抽象类中的方法才可以被实例化,否则该类仍然需要
被声明为抽象类
(28)抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?
- 都不能。
- 抽象方法需要被子类重写,而静态的方法是无法被重写的。
- 本地方法是由本地代码实现的,而抽象方法是没有实现的。
- synchronized和方法与实现细节有关,抽象方法不涉及实现细节。
(29)如何实现对象克隆?
- 实现Cloneable接口并重写Object类中的clone()方法。
- 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。
**(30)GC是什么?为什么要有GC?
- GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显示的垃圾回收调用。
(31)接口是否可继承(extends)接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)?
- 接口可以继承接口
- 抽象类可以实现接口
- 抽象类可继承具体类,但前提是具体类必须有明确的构造函数。
(32)内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?
- 一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。
(33)数据类型之间的转换
- 低级到高级的自动类型转换;
- 高级到低级的强制类型转换(会导致溢出或丢失精度);
- 基本类型向类类型转换;
(34)怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?
String s1 = "你好";
String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");
(35)如何实现字符串的反转及替换?
public static String reverse(String originStr) {
if(originStr == null || originStr.length() <= 1)
return originStr;
return reverse(originStr.substring(1)) + originStr.charAt(0);
}
(36)打印昨天的当前时刻。
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
System.out.println(cal.getTime());
(37)比较一下Java 和JavaSciprt
- 基于对象和面向对象
- 解释和编译
- 强类型变量和类型弱变量
- 代码格式不一样
(38)Error 和Exception 有什么区别?
- Error 表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;
- Exception 表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。
(39)Java 语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?
- Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java 中,每个异常都是一个对象,它是Throwable 类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。
- try用来指定一块预防所有异常的程序;
- catch子句紧跟在try块后面,用来指定你想要捕捉的异常的类型;
- throw语句用来明确地抛出一个异常;
- throws用来标明一个成员函数可能抛出的各种异常;
- finally为确保一段代码不管发生什么异常都被执行一段代码
(40)运行时异常与受检异常有何异同?
- 异常表示程序运行过程中可能出现的非正常状态。
- 运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。
- 受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。
(41)列出一些你常见的运行时异常?
- ArithmeticException(算术异常)
- ClassCastException (类转换异常)
- IllegalArgumentException (非法参数异常)
- IndexOutOfBoundsException (下标越界异常)
- NullPointerException (空指针异常)
- SecurityException (安全异常)
(42)什么是泛型,有哪些优点?
- 是JDK1.5的新特性,本质是参数化类型,即所操作的数据类型被指定为一个参数,使用时通过传参来指定具体的类型。
- 安全简单:具体体现在提供编译时的强类型检查,而不用等到运行;可避免类类型强制转换;增强代码可读性。
(43)设计一个图片缓存加载机制
- 先检查在内存中是否存在该图片
- 在检查在硬盘中是否存在该图片
- 最后在网络上获取图片
(44)同步和非同步、阻塞和非阻塞的概念
- 同步:方法A调用方法B后必须等到方法B返回结果才能继续后面的操作。
- 异步:方法A调用方法B后可让方法B在调用结束后通过回调等方式通知方法A。
- 阻塞,就是在结果返回之前让当前线程挂起。
- 非阻塞,就是在等待时可做其他事情,通过轮询去询问是否已返回结果。
**(45)什么是反射,有什么作用和应用?
- java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
- 根据类名动态创建类的对象
- 动态创建数组对象,对数组元素复制和取值。
二、JVM
(1)JVM内存是如何划分的?
- 堆区 :通常就是指在程序运行时直接 new 出来的内存,也就是对象的实例。这部分内存在不使用时将会由 Java 垃圾回收器来负责回收。
- 栈区 :用于存储方法体内的局部变量,并在方法执行结束时这些局部变量所持有的内存将会自动被释放。
- 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
(2)谈谈垃圾回收机制?为什么引用计数器判定对象是否回收不可行?知道哪些垃圾回收算法?
- 引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。然而在主流的Java虚拟机里未选用引用计数算法来管理内存,主要原因是它难以解决对象之间相互循环引用的问题,所以出现了另一种对象存活判定算法。
- 可达性分析法:通过一系列被称为『GC Roots』的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
(3)描述一下JVM 加载class文件的原理机制?
- JVM 中类的装载是由类加载器(ClassLoader) 和它的子类来实现的,Java中的类加载器是一个重要的Java 运行时系统组件,它负责在运行时查找和装入类文件中的类。
(4)类加载的全过程是怎样的?什么是双亲委派模型?
- 类加载机制:是虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可被虚拟机直接使用的Java类型的过程。
- 双亲委派模型:表示类加载器之间的层次关系。
(5)JVM、Dalvik、ART的区别?
- Java虚拟机:Java虚拟机基于栈,基于栈的机器必须使用指令来载入和操作栈上数据;Java虚拟机运行的是java字节码;JVM在运行的时候为每一个类装载字节码。
- Dalvik虚拟机:Dalvik虚拟机基于寄存器;Dalvik运行的是自己专属的.dex字节码格式;一个应用对应一个Diavik虚拟机实例,独立运行;Dalvik程序只包含一个.dex文件,这个文件包含了程序中所有的类。
- ART虚拟机:ART 的机制与 Dalvik 不同。在Dalvik下,应用每次运行的时候,字节码都需要通过即时编译器(just in time ,JIT)转换为机器码,这会拖慢应用的运行效率,而在ART 环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。这个过程叫做预编译(AOT,Ahead-Of-Time)。这样的话,应用的启动(首次)和执行都会变得更加快速。
(6)Dalvik和Java运行环境的区别
- Dalvik主要完成对象生命周期管理,堆栈管理,线程管理,安全和异常管理,以及垃圾回收等重要功能
- Dalvik负责进程隔离和线程管理,每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。
- 不同于Java虚拟机运行Java字节码,Dalvik虚拟机运行的是其专有的文件格式Dex
- dex文件格式可以减少整体文件尺寸,提高I/O操作的类查找速度
- odex是为了在运行过程中进一步提高性能,对dex文件的进一步优化。
(7)Dalvik和ART的区别
- ART能够把应用程序的字节码转为机器码,是Android所使用的一种新的虚拟机,与Dalvik不同在于:Dalvik采用的是JIT技术而ART采用Ahead-of-time(AOT)技术。ART同时也改善了性能,垃圾回收机制,应用程序出错以及性能分析
- ART引入了AOT这种预编译技术,在应用程序安装的过程中,ART就已经将所有的字节码重新编译成机器码。应用程序运行过程中无需进行实时的编译工作,只需要进行直接调用,因此ART极大的提高了应用程序的运行效率,同时也减少了手机的电量消耗,在垃圾回收机制等机制上也有了较大的提升。
- 相对于Dalvik虚拟机模式。ART模式下Android应用程序的安装需要消耗更多的时间,同时也会占用更大的存储空间(指内部存储,用于存储编译后的代码),但节省了很多Dalvik虚拟机用于实时编译的时间
三、计算机网络
(1)TCP和UDP的区别?
- TCP传输控制协议:面向连接;使用全双工的可靠信道;提供可靠的服务,即无差错、不丢失、不重复且按序到达;拥塞控制、流量控制、超时重发、丢弃重复数据等等可靠性检测手段;面向字节流;每条TCP连接只能是点到点的;用于传输可靠性要求高的数据。
- UDP用户数据报协议:无连接;使用不可靠信道;尽最大努力交付,即不保证可靠交付;无拥塞控制等;面向报文;支持一对一、一对多、多对一和多对多的交互通信;用于传输可靠性要求不高的数据。
(2)拥塞控制和流量控制都是什么,两者的区别?
- 拥塞控制:对网络中的路由和链路传输进行速度限制,避免网络过载;包含四个过程:慢启动、拥塞避免、快重传和快恢复。
- 流量控制 :对点和点/发送方和接收方之间进行速度匹配,由于接收方的应用程序读取速度不一定很迅速,加上缓存有限,因此需要避免发送速度过快。
(3)谈谈TCP为什么要三次握手?为什么要四次挥手?
- 客户端向服务端发送一个表示建立连接的报文段SYN报文段;一旦包含SYN报文段的IP数据报到达服务器主机,服务器从IP数据报中提取出TCP、SYN报文段,为该TCP连接分配需要的缓存和变量,并向客户端发送表示允许连接的报文段ACK;在收到ACK报文段之后,客户端也要给该连接分配缓存和变量,客户端向服务器再发送一个报文段ACK,表示对允许连接的报文段进行了确认。自此完成一次TCP连接。
- 由于TCP连接是全双工的,因此每个方向都必须单独关闭。客户端在数据发送完毕后发送一个结束数据段FIN,且服务端也返回确认数据段ACK,此时结束了客户端到服务端的连接;然后客户端接收到服务端发送的FIN,且服务端也收到了ACK之后,自此双方的数据通信完全结束。
(4)播放视频用TCP还是UDP?为什么?
- 播放视频适合用UDP。UDP适用于对网络通讯质量要求不高、要求网络通讯速度能尽量快的实时性应用;而TCP适用于对网络通讯质量有要求的可靠性应用。
(5)get和post的区别?
- 一般用于获取/查询资源信息;GET参数通过URL传递,传递的参数是有长度限制,不能用来传递敏感信息。
- 当客户端给服务器提供信息较多时可以使用POST;POST会附带用户数据,一般用于更新资源信息;POST将请求参数封装在HTTP 请求数据中,可以传输大量数据,传参方式比GET更安全。
(6)HTTP和TCP的区别
- TCP是传输层协议,定义数据传输和连接方式的规范。通过三次握手建立连接、四次挥手释放连接。
- HTTP是应用层协议,定义的是传输数据的内容的规范。HTTP的连接使用"请求-响应"方式。基于TCP协议传输。
(7)HTTP和Socket的区别
- HTTP是应用层协议;基于TCP协议;使用“请求—响应”方式建立连接,在请求时需要先建立连接且客户端要先发出请求,可见服务器需要等到客户端发送一次请求后才能将数据传回给客户端。
- Socket(套接字)是对TCP/IP协议的封装,是接口而不是协议;创建Socket连接时可以指定传输层协议TCP或UDP;Socket建立连接过程三步骤:服务器监听->客户端请求->连接确认,可见服务器可以直接将数据传送给客户端。
(8)HTTP2.0与HTTP1.1的区别
- HTTP1.1一个请求完成后再发另一个请求.
- 并发,但请求结果的返回过程必须是顺序的,第一个响应完成后,才能响应第二个,即使第二个先处理完成,也要等待第一个,就产生了阻塞
- HTTP2.0并发,只要有了请求结果数据,可以立即返回,不关心顺序问题,因为数据都被组装成了一个个的frame帧,frame中记录了自己所属数据流的ID,客户端把frame都接收到以后,根据数据流ID再进行组装即可