以下为《java基础知识面试题》的无排版文字预览,完整内容请下载
面试题
Java
运行机制
Java跨平台原理
/
Java实现跨平台是JVM(Java虚拟机)起的作用。如果是C/C++的编译方式,一旦换了一个平台,那么就需要重新编译一份对应的可执行代码,但是Java则不同,编译好了一份Java字节码,换到不同的平台上时,并不需要重新编译,前提是这些平台上都安装了相应平台的JVM,JVM不是跨平台的。
垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
垃圾回收器通常是作为一个单独的低级别的线程运行,在不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。
垃圾回收器不可以马上回收内存,程序员可以手动执行System.gc(),通知GC运行, 但是Java语言规范并不保证GC一定会执行。
垃圾回收机制
分代复制垃圾回收
不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。?在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如Http请求中的?Session对象、线程、Socket连接,这类对象跟业务直接挂钩,因此生命周期比较长。 但是还有一些对象,主要是程序运行过程中生成的临时变量,这些对象生命周期会比较 短,比如:String对象,由于其不变类的特性,系统会产生大量的这些对象,有些对象甚至只用一次即可回收。如果每次垃圾回收都是对整个堆空间进行回收,花费时间相对会长,并且生命周期长的对象依旧存在,因此引入分代回收,把不同生命周期的对象 放在不同代上,不同代上采用最适合它的垃圾回收方式进行回收。
虚拟机中的共划分为三个代:年轻代(Young Generation)、年老点(Old Generation)和持久代(Permanent Generation)。由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。
标记垃圾回收
在使用标记清除算法时,未引用对象并不会被立即回收.取而代之的做法是,垃圾对象将一直累计到内存耗尽为止.当内存耗尽时,程序将会被挂起,垃圾回收开始执行.当所有的未引用对象被清理完毕时,程序才会继续执行。
标记清除算法由两个阶段组成:?
?标记阶段,标记所有的可访问对象。
?收集阶段,垃圾收集算法扫描堆并回收所有的未标记对象。
增量垃圾回收
简单地说,它的存在是为了解决标记清除的长停顿问题。增量收集器把堆栈分为多个域,每次仅从一个域收集垃圾。这会造成较小的应用程序中断。
JVM加载class文件的原理机制?
答:JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。
由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。
类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,包括:
1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;
2)如果类中存在初始化语句,就依次执行这些初始化语句。
类的加载是由类加载器完成的,类加载器包括:
Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);
Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;
System:又叫应用类加载器,其父类是Extension。它是应用最广泛的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。
Java内存
堆(heap)与栈(stack)
在java中,Main函数就是栈的起始点,也是程序的起始点。程序要运行总是有一个起点的(程序执行的入口)。
?
/
概括:
?1.栈是运行时的单位 ,?而堆是存储的单元。
?2.栈解决程序的运行问题,即程序如何执行,或者说如何处理数据,
? ?堆解决的是数据存储的问题,即数据怎么放,放在哪儿。
在java中一个线程就会相应有一个线程栈与之对应,这点很容易理解,因为不同的线程执行逻辑有所不同,因此需要一个独立的线程栈。
而堆则是所有线程共享的。
?疑问一:为什么要把堆和栈区分出来呢?栈中不是也可以存储数据吗?
???? 1. 从软件设计的角度看,栈代表了处理逻辑,而堆代表了数据。这样分开,使得处理逻辑更为清晰。分而治之的思想。
? ? 这种隔离、模块化的思想在软件设计的方方面面都有体现。
???? 2.堆与栈的分离,使得堆中的内容可以被多个栈共享(也可以理解为多个线程访问同一个对象)。
? ? ? ? 好处: ?a.提供了一种有效的数据交互方式(如:共享内存)
? ? ? ? ? ? ? ? ?b.堆中的共享常量和缓存可以被所有栈访问,节省了空间。
???? 3. 栈因为运行时的需要,比如保存系统运行的上下文,需要进行地址段的划分。
? ? ? ? 由于栈只能向上增长,因此就会限制住栈存储内容的能力,
? ? ? ? 而堆不同,堆中的对象是可以根据需要动态增长的,
? ? ? ? 因此栈和堆的拆分使得动态增长成为可能,相应栈中只需记录堆中的一个地址即可。
???? 4.?面向对象就是堆和栈的完美结合。
? ? 其实,面向对象方式的程序与以前结构化的程序在执行上没有任何区别。
? ? 但是,面向对象的引入,使得对待问题的思考方式发生了改变,而更接近于自然方式的思考。
? ? 当我们把对象拆开,你会发现,对象的属性其实就是数据,存放在堆中;
? ? ? ? 而对象的行为(方法),就是运行逻辑,放在栈中。
? ? ? ? 我们在编写对象的时候,其实就是编写了数据结构,也编写了处理数据的逻辑。不得不承认,面向对象的设计,确实很美。
?疑问二:??堆中存什么?栈中存什么?
? ? ?1. 栈存储的信息都是跟当前线程(或程序)相关的信息。(局部变量、程序运行状态、方法、方法返回值)等,
? ? ? ? ?栈中存的是基本数据类型和堆中对象的引用。一个对象的大小是不可估计的,或者说是可以动态变化的,但是
? ? ? ? ?在栈中,一个对象只对应了一个4byte的引用(堆栈分离的好处)。
? ? ?2. 堆只负责存储对象信息。
?疑问三:? 为什么不把基本类型放堆中呢?
? ? ?1. 其占用的空间一般是1~8个字节---需要空间比较少,
? ? ?2.而且因为是基本类型,所以不会出现动态增长的情况---长度固定,因此栈中存储就够了,如果把它存在堆中是没有什么意义的(还会浪费空间)。
疑问四:??java中的参数传递是传值呢?还是传引用?
? ? ?对象传递是引用值传递,原始类型数据传递是值传递
? ? ?实际上这个传入函数的值是对象引用的拷贝,即传递的是引用的地址值,所以还是按值传递
? ? ? 堆和栈中,栈是程序运行最根本的东西。程序运行可以没有堆,但是不能没有栈。
? ? ? 而堆是为栈进行数据存储服务的,堆就是一块共享的内存。
? ? 不过,正是因为堆和栈的分离的思想,才使得java的垃圾回收成为可能。
? ? ??java中,栈的大小通过-Xss来设置,当栈中存储的数据比较多时,需要适当调大这个值,否则会出现?java.lang.StackOverflowError异常。
Dd
D
基础语法
一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?
可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。
一个文件中可以只有非public类,如果只有一个非public类,此类可以跟文件名不同
&和&&的区别。
&和&&都可以用作逻辑与的运算符,&&为短路与,&不是短路与。
另外&可以做为整数的位运算符
例1:对于if(str != null&& !str.equals(“”))表达式,当str为null时,后面的表达式不会执行,所以不会出现NullPointerException如果将&&改为&,则会抛出NullPointerException异常。
例2:If(x==33 &++y>0) y会增长,If(x==33 && ++y>0)不会增长
java中int数据占几个字节
/
Integer与int的区别
int是java提供的8种原始数据类型之一,另外Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。
如在业务中表示year,如果用int,在没有赋值时,int类型会给一个默认值0,这样就不知道这个year=0,是手工还是默认给的值,而定义成Integer则在没有赋值时是null,推荐使用封装类型。
表示钱: BigDecimal或Integer(表示分)
请设计一个一百亿的计算器
如果只是大整数运算,使用BigInteger就可以
如果有浮点数据参与去处,需要使用BigDecimal进行运算
Java中基本类型的浮点数运算是不精确的,需要使用BigDecimal运算,尤其是金融、会计方向的软件
char型变量中能不能存贮一个中文汉字?
char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中可以存储汉字。
short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
对于short s1 = 1; s1 = s1 + 1;由于s1+1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器会提示错误,需要强制转换类型。
对于short s1 = 1; s1 += 1;由于+=是java语言规定的运算符,Java编译器会对它进行特殊处理,因此可以正确编译。
"=="和equals方法有什么区别?
==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。
如果一个变量指向的数据是对象类型的,那么这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。
equals方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:
String a=new String("foo");
String b=new String("foo");
两条new语句创建了两个对象,然后用a,b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。
在实际开发中,我们经常要比较传递进行来的字符串内容是否等,例如,String input =…;input.equals(“quit”),如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下:
boolean equals(Object o){
return this==o;
}
这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。
当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。?
hashcode这个方法是用来鉴定2个对象是否相等的。hashcode方法一般用户不会去调用,比如在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就判断了hashcode这个方法,而且也用到了equals方法。这里不可以重复是说equals和hashcode只要有一个不等就可以了。所以简单来讲,hashcode相当于是一个对象的编码。我们一般在覆盖equals的同时也要覆盖hashcode,让他们的逻辑一致。
作用域public,private,protected,以及不写时的区别?
修饰符 当前类 同 包 子 类 其他包
public √ √ √ √
protected √ √ √ ×
default √ √ × ×
private √ × × ×
类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。
受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。
Java中,外部类的修饰符只能是public或默认,类的成员(包括内部类)的修饰符可以是以上四种。
Java 常用包
java.lang--语言包:Java语言的基础类,包括Object类、Thread类、String、Math、System、Runtime、Class、Exception、Process等,是Java的核心类库
java.util--实用工具包:Scanner、Date、Calendar、LinkedList、Hashtable、Stack、TreeSet等;
java.NET--网络功能包:URL、Socket、ServerSocket等;
java.sql--数据库连接包:实现JDBC的类库;
java.io--输入输出包:提供与流相关的各种包;
Java常用接口
?Comparable ,Collection,Set, List, Map, Runnable Iterable Iterator 等
D
Dd
d
面向对象
你对面向对象思想的理解?
面向对象编程(Object-Oriented Programming)简称OOP技术,是开发计算机应用程序的一种新方法、新思想。过去的面向过程编程中常常会导致所有的代码都包含在几个模块中,使程序难以阅读和维护,在做一些修改时常常牵一动百,使以后的开发和维护难以为继。而使用OOP技术,使用许多代码模块,每个模块都只提供特定的功能,它们是彼此独立的,可以增加代码重用的几率,更加有利于软件的开发、维护和升级。另外OOP的三大核心特性:继承、封装、多态的特性,使得在面对象编上能够设计出高某某、低耦合的系统结构,使得系统更灵活、更容易扩展,而且成本较低,所以这一编程思想是目前一种应用最为普遍的软件设计思想。
封装
封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高某某、低耦合”,防止程序相互依赖性而带来的变动影响。面向对象的封装就是把描述一个对象的属性和行为的代码封装在一个“模块”中,也就是一个类中,属性用变量定义,行为用方法进行定义,方法可以直接访问同一个对象中的属性。
继承
在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性。
多态
多态指的同一个对象,在程序不同时刻的多种运行状态。举例:水(气态,液态,固态)。
所谓多态,指的就是父类引用指向子类对象,调用方法时会调用子类的实现而不是父类的实现。多态的实现的关键在于“动态绑定”。
为使多态能运行,存在着继承或者实现关系
可以将子类的对象赋给父类/接口,以多态的形式来传递参数,增强了参数类型的灵活性。即父类(接口)引用指向子类(实现)对象
多态的好处和弊端:
好处:多态的存在提高了程序的扩展性和后期可维护性
弊端:虽然可以预先使用,但是只能访问父类中已有的功能,运行的是后期子类的功能内容。不能预先使用子类中定义的特有功能。
多态应用场景:当接口已经确定,但同一个接口在不同环境需要不同实现的时候。如:工厂模式
工厂方法模式(Factory Mehtod Pattern):定义一个用于创建对象的接口,让子类决定哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又称为工厂模式,又称为虚拟构造器模式或多态工厂模式。工厂方法模式是一种类创建型模式。
object中定义了哪些方法?
protected Object?? clone()创建并返回此对象的一个副本。???boolean?? equals(Object obj)指示其他某个对象是否与此对象“相等”。???protected void?? finalize()当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。???Class?? getClass()返回此 Object 的运行时类。???int?? hashCode()返回该对象的哈希码值。???void?? notify()唤醒在此对象监视器上等待的单个线程。???void?? notifyAll()唤醒在此对象监视器上等待的所有线程。???String?? toString()返回该对象的字符串表示。???void?? wait()在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。???void?? wait(long timeout)在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。???void?? wait(long timeo 内容过长,仅展示头部和尾部部分文字预览,全文请查看图片预览。
}
输入一行字符,请统计出这中间的空格、英文字母、数字以及其他字符的个数
/
完数
一个数如果恰好等于它的因子之和,这个数就称为 "完数 "。例如6=1+2+3.编程 找出1000以内的所有完数。
/
给一个不多于5位的正整数,要求:一、求它是几位数,二、逆序打印出各位数字。
/
有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成最前面的m个数
/
如何把一段逗号分割的字符串转换成一个数组?
1)用正则表达式,代码大概为:String [] result = orgStr.split(“,”, -1);
2)用 StingTokenizer ,代码为:
StringTokenizer tokener = new StringTokenizer(s, ",");
String[] result = new String[tokener.countTokens()];
Integer i = 0;
while (tokener.hasMoreTokens()) {
result[i++] = tokener.nextToken();
}
D
D
d
Dd
D
D
D
D
[文章尾部最后500字内容到此结束,中间部分内容请查看底下的图片预览]请点击下方选择您需要的文档下载。
以上为《java基础知识面试题》的无排版文字预览,完整内容请下载
java基础知识面试题由用户“wnwn125”分享发布,转载请注明出处