面试题整理(持续更新)

来源:互联网 发布:手机上怎么找淘宝链接 编辑:程序博客网 时间:2024/05/16 17:35
下面程序的运行结果是什么()
class HelloA {


    public HelloA() {
        System.out.println("HelloA");
    }
    
    { System.out.println("I'm A class"); }
    
    static { System.out.println("static A"); }


}


public class HelloB extends HelloA {
    public HelloB() {
        System.out.println("HelloB");
    }
    
    { System.out.println("I'm B class"); }
    
    static { System.out.println("static B"); }
    




    public static void main(String[] args) { 
     new HelloB(); 
   }


}




答案:


4.答案:
static A
static B
I'm A class
HelloA
I'm B class
HelloB
解析:说实话我觉得这题很好,考查静态语句块、构造语句块(就是只有大括号的那块)以及构造函数的执行顺序。
对象的初始化顺序:(1)类加载之后,按从上到下(从父类到子类)执行被static修饰的语句;(2)当static语句执行完之后,再执行main方法;


(3)如果有语句new了自身的对象,将从上到下执行构造代码块、构造器(两者可以说绑定在一起)。
下面稍微修改下上面的代码,以便更清晰的说明情况:
\ View Code
此时输出结果为:
复制代码
static A
static B
-------main start-------
I'm A class
HelloA
I'm B class
HelloB
I'm A class
HelloA
I'm B class
HelloB
-------main end-------
复制代码




在switch(表达式)语句中,表达式的类型不能为(     c )。   
A  byte   B  char   C  long   D  int




分析选项中关于Java中this关键字的说法正确的是(  a) ?
A、 this关键字是在对象内部指代自身的引用
 B、 this关键字可以在类中的任何位置使用 (静态方法)
C、 this关键字和类关联,而不是和特定的对象关联
 D、 同一个类的不同对象共用一个this 


当线程因异常而退出run()后,此时线程的状态为(     d   )。
A    阻塞状态
B    运行状态
C    就绪状态
D   结束状态




简述==与equals有什么区别?


==比较的是一个对象在内存中的地址值, 比如2个字符串对象 String s1 = new String("str"); String s2 = new String("str"); 如果用==号比较,会返回false,因为创建了两个对象,他们在内存中地址的位置是不一样的;
equals是java.lang.Object类中的一个方法,因为java中所有的类都默认继承于Object,所以所有的类都有这个方法。不过大部分常用的API类对此方法进行了重写,所以上述例子中如果使用equals方法进行比较,返回结果就是true。



对于==,如果两边是数值,表示判断数值是否相等,如果两边是引用类型,表示对象是否相等。


equals(),判断两个对象的内容是否相同。


例子:

string s1 = "hello";                在静态常量池初始化

string s2 = new string("hello");

string s3 = new string("hello");


system.out.println(s1==s2);//false

system.out.println(s2==s3);//false

system.out.println(s1.equals(s2));//true

system.out.println(s2.equals(s3));//true






已有字符串"yekmaakkccekymbvb",编程求字符串中有多少种字符以及每个字符的个数


思路:装换成char类型数组,装进Map集合里面利用key和value分别对应字母和所占个数,利用循环遍历输出


用到方法:containkey

get put


int与integer的区别?

integer是int类型的封装类

int不是对象    基本类型

integer是对象   引用类型


java中的引用和c中的指针的区别?

简答:应用是相当于更安全的指针

c 的指针可以指向任意的内存空间,得到的是真实的内存地址。

java的语言不允许引用进行数学运算,也得不到真实的内存地址。


sleep()与wait()的区别

sleep()交出CPU时间片,休眠指定时间后,重新进入可运行状态,wait()释放CPU资源,

进入等待队列后积极地等待被唤醒。

sleep()不会释放对象的锁,wait()释放对象的锁。

sleep()属于Thread类的静态方法,wait()属于Object类的成员方法。

sleep()可以在任何地方调用,wait()只能在同步代码块中调用。



一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?

答:可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。



switch语句能否作用在byte上,能否作用在long上,能否作用在String上?

答:switchexpr1)中,expr1只能是一个整数表达式或者枚举常量(更大字体),整数表达式可以是int基本类型或Integer包装类型,由于,byte,short,char都可以隐含转换为int,所以,这些类型以及这些类型的包装类型也是可以的。显然,longString类型都不符合switch的语法规定,并且不能被隐式转换成int类型,所以,它们不能作用于swtich语句中。但是在JDK7的新特性中,switch语句可以用字符串。



用最有效率的方法算出2乘以8等於几?

答:2 << 3,因为将一个数左移n位,就相当于乘以了2n次方,那么,一个数乘以8只要将其左移3位即可,而位运算cpu直接支持的,效率最高,所以,2乘以8等於几的最效率的方法是2 << 3



解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法?

答:①通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间;

而通过new关键字和构造器创建的对象放在堆空间;

程序中的字面量(literal)如直接书写的100"hello"和常量都是放在静态区中。

④栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,理论上整个内存没有被其他进程使用的空间甚至硬盘上的虚拟内存都可以被当成堆空间来使用。

⑤例如:String str = new String("hello");

上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而"hello"这个字面量放在静态区。


数组有没有length()方法?String有没有length()方法? 

答:数组没有length()方法,有length的属性。Stringlength()方法。JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆。


是否可以继承String类? 

答:String 类是final类,不可以被继承。

补充:继承String本身就是一个错误的行为,对String类型最好的重用方式是关联关系(Has-A)和依赖关系(Use-A)而不是继承关系(Is-A)。



描述一下JVM加载class文件的原理机制? 

答:JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的类。

由于Java的跨平台性,经过编译的Java源程序并不是一个可执行程序,而是一个或多个类文件。当Java程序需要使用某个类时,JVM会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的Class对象。加载完成后,Class对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。最后JVM对类进行初始化,包括:1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;2)如果类中存在初始化语句,就依次执行这些初始化语句。

类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)。从Java 2JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好的保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。下面是关于几个类加载器的说明:

Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);

Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap

System:又叫应用类加载器,其父类是Extension。它是应用最广泛的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。




抽象的(abstract)方法是否可同时是静态的(static,是否可同时是本地方法(native),是否可同时被synchronized修饰? 

答:都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。



String st = null和 String st =“ ”的区别?String s = new String("xyz")创建了几个对象? 

答:(1String st = null表示声明了一个String对象的引用str,但是没有为其分配存内存空间。

2String st =“ ”表示创建了一个长度等于0的空字符串,并在内存中分配了内存空间。

3String st = new String(xyz”);表示创建了两个对象:

         ①堆内存中一个new String

         ②常量池中一个字符串。


接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)? 

答:接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。


内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制? 

答:一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。



finalizedObject类中的方法,其中定义了对象要被垃圾回收器回收之前,要做的一些清理工作。



数据类型之间的转换? 

答:(1)如何将字符串转换为基本数据类型?

调用基本数据类型对应的包装类中的方法parseXXX(String)valueOf(String)即可返回相应基本类型;

   (2)如何将基本数据类型转换为字符串?

一种方法是将基本数据类型与空字符串("")连接(+)即可获得其所对应的字符串另一种方法是调用String类中的valueOf()方法返回相应字符串



ErrorException有什么区别?

答:①Error表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;

②Exception表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。



throwthrows的区别、及处理方式?

答:(1throw:用于抛出异常对象,后面跟的是异常对象;throw用在方法体内;

   2throws:用于抛出异常类,后面跟的是异常类名,可以跟多个,用逗号隔开。throws用在方法上

   3)异常处理方式:抛出throws、捕捉try - catch - finally

   4)什么时候定义try,什么时候定义throws

        ①功能内部如果出现异常,如果可以处理,就用try

        ②如果内部处理不了,就必须声明出来,让调用者处理。


CollectionCollections的区别? 

答:Collection是一个接口,它是SetList等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。



简述线程的五种状态?

答:(1)新建(new):当一个线程处于新建状态时,它仅仅是一个空的线程对象,系统不为它分配资源。Tread t = new Tread(new Runner());

   2)就绪(Runable):此时线程处在随时可以运行的状态,在随后的任意时刻,都可能进入运行状态。t.star( );

   3)运行(Running):处于这个状态的线程占用CPU,执行程序代码。

   4)阻塞(Blocked):阻塞状态是指线程因为某些原因放弃CPU,暂时停止运行,直到线程重新进入就绪状态。waitsleep、同步锁被占用;

   5)死亡(Dead):当线程退出run()方法时,就进入死亡状态,该线程生命周期结束。可能正常执行完run()方法退出,也可能是遇到异常。



.举例说明同步和异步。

答:如果系统中存在临界资源(资源数量少于竞争资源的线程数量的资源),例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就必须进行同步存取(数据库操作中的排他锁就是最好的例子)。当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。事实上,所谓的同步就是指阻塞式操作,而异步就是非阻塞式操作。


什么是线程池(thread pool)?

答:在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁,这就是”池化资源”技术产生的原因。线程池顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。



JDBC中如何进行事务处理? 

答:Connection提供了事务处理的方法,通过调用setAutoCommit(false)可以设置手动提交事务;当事务完成后用commit()显式提交事务;如果在事务处理过程中发生异常则通过rollback()进行事务回滚。除此之外,从JDBC 3.0中还引入了Savepoint(保存点)的概念,允许通过代码设置保存点并让事务回滚到指定的保存点。


简述一下面向对象的"六原则一法则" 

答: (1)单一职责原则一个类只做它该做的事情。其核心就是我们常说的"高内聚",写代码最终极的原则只有六个字"高内聚、低耦合",就像葵花宝典的八字中心思想一样"欲练此功必先自宫"一样重要。我们都知道一句话叫"因为专注,所以专业",一个对象如果承担太多的职责,那么注定它什么都做不好。这个世界上任何好的东西都有两个特征,一个是功能单一,好的相机绝对不是电视购物里面卖的那种一个机器有一百多种功能的,它基本上只能照相;另一个是模块化,好的自行车是组装车,从减震叉、刹车到变速器,所有的部件都是可以拆卸和重新组装的,这从我们的框架演化的过程中也可以开出来:。。。。

    (2)开闭原则软件实体应当对扩展开放,对修改关闭。(在理想的状态下,当我们需要为一个软件系统增加新功能时,只需要从原来的系统派生出一些新类就可以,不需要修改原来的任何一行代码。要做到开闭有两个要点:

       ①抽象是关键,一个系统中如果没有抽象类或接口系统就没有扩展点;

       ②封装可变性,将系统中的各种可变因素封装到一个继承结构中,如果多个可变因素混杂在一起,系统将变得复杂而换乱。)

    (3)依赖倒转原则:面向接口编程。(该原则说得直白和具体一些就是声明方法的参数类型、方法的返回类型、变量的引用类型时,尽可能使用抽象类型而不用具体类型,因为抽象类型可以被它的任何一个子类型所替代,请参考下面的里氏替换原则。)

    (4)里氏替换原则任何时候都可以用子类型替换掉父类型。(关于里氏替换原则的描述,Barbara Liskov女士的描述比这个要复杂得多,但简单的说就是能用父类型的地方就一定能使用子类型。里氏替换原则可以检查继承关系是否合理,如果一个继承关系违背了里氏替换原则,那么这个继承关系一定是错误的,需要对代码进行重构。例如让猫继承狗,或者狗继承猫,又或者让正方形继承长方形都是错误的继承关系,因为你很容易找到违反里氏替换原则的场景。需要注意的是:子类一定是增加父类的能力而不是减少父类的能力,因为子类比父类的能力更多,把能力多的对象当成能力少的对象来用当然没有任何问题。)

    (5)接口隔离原则接口要小而专,绝不能大而全。(臃肿的接口是对接口的污染,既然接口表示能力,那么一个接口只应该描述一种能力,接口也应该是高度内聚的。例如,琴棋书画就应该分别设计为四个接口,而不应设计成一个接口中的四个方法,因为如果设计成一个接口中的四个方法,那么这个接口很难用,毕竟琴棋书画四样都精通的人还是少数,而如果设计成四个接口,会几项就实现几个接口,这样的话每个接口被复用的可能性是很高的)

    (6)聚合复用原则:优先使用聚合关系复用代码。(通过继承来复用代码是面向对象程序设计中被滥用得最多的东西,因为所有的教科书都无一例外的对继承进行了鼓吹从而误导了初学者,类与类之间简单的说有三种关系,Is-A关系、Has-A关系、Use-A关系,分别代表继承、关联和依赖。其中,关联关系根据其关联的强度又可以进一步划分为关联、聚合和合成,但说白了都是Has-A关系,合成聚合复用原则想表达的是优先考虑Has-A关系而不是Is-A关系复用代码例如Properties类继承了Hashtable类,API中原话:因为 Properties 继承于 Hashtable,所以可对Properties 对象应用put putAll 方法。但不建议使用这两个方法,因为它们允许调用者插入其键或值不是String 的项。相反,应该使用setProperty 方法。这继承明显就是错误的,更好的做法是在Properties类中放置一个Hashtable类型的成员并且将其键和值都设置为字符串来存储数据。)

   (7)迪米特法则迪米特法则又叫最少知识原则,一个对象应当对其他对象有尽可能少的了解。(迪米特法则简单的说就是如何做到"低耦合"门面模式和调停者模式就是对迪米特法则的践行。对于门面模式可以举一个简单的例子,你去一家公司洽谈业务,你不需要了解这个公司内部是如何运作的,你甚至可以对这个公司一无所知,去的时候只需要找到公司入口处的前台美女,告诉她们你要做什么,她们会找到合适的人跟你接洽,前台的美女就是公司这个系统的门面。再复杂的系统都可以为用户提供一个简单的门面,Java Web开发中作为前端控制器的ServletFilter不就是一个门面吗。调停者就是中间人,中间件dubbo为例



hashCode方法的作用?

答:hashcode这个方法是用来鉴定2个对象是否相等的。与equals方法的区别:

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

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

要从物理上判断2个对象是否相等,用==就可以了。




传统for循环、增强for循环、及迭代器的区别?

答:1)传统for循环:可以定义角标,通过角标操作元素。

2)增强for循环:对集合进行遍历,集合不能为空。只能获取集合元素,无法获取角标,不能对集合进行操作。增强for循环有一个局限性,必须要有被遍历的目标。

3)迭代器(Iterator):除了遍历,还可以进行remove集合中元素的动作。如果是用ListIterator,还可以在遍历过程中进行增删改的动作。



JDK和JRE的区别是什么?它们各自有什么作用?

jdk是java开发工具,它不仅提供了java程序运行所需的jre,还提供了一系列的编译、运行等工具,如

javac 、java、javaw等。 jre只是java程序的运行环境,它最核心的内容是jvm(java虚拟机)及核心类库。 



请简述jva中的main()方法

main()方法是java程序的执行入口,它是一个定义在类中的、公开的

、静态的、无返回值的、参数为一个字符串数组的方法,它的参数args与执行参数一一对应。




equal和==的区别


== 运用在基本数据类型的时候,通过比较它们实际的 值来判定是否相同;而用户比较引用类型的时候,则是

比较两个引用的地址是否相等,也就是是否指向同一个对象


equal方式是object的方法,也就是所以java的类都会有的方法。它可以被覆盖重写,通过自定义的方式来判定两个对象是否相等。

对于String类来说,他的equal方法来比较字符串的字符序列是否完全相等。



简述静态成员的特点


类的静态成员是通过static关键字流失得成员,主要包括:静态成员变量、

静态方法、和静态代码块,他们具有以下一些特点。

1.在类加载的时候,就进行创建和初始化或执行代码。

2.他们对于一个雷来说,都只有一份。

3.类的所有势力都可以访问到它们。


int和integer

int是基础数据类型,字节长度为4, 它的创建不会再堆内存中开辟空间,一般保存在栈内存里,可以用算术运算符进行加减乘除等操作。

在参数传递的时候,直接传递它的值。

integer是int的包装类,而本质只是一个类,它的创建会在堆内存中开辟一块新的空间。

它的含义也是表示一个类型的数字,但是,算术运算符不能操作它。在参数传递的时候,

传递的是它所代表的对象的一个引用。






原创粉丝点击