Java面试题集(三)

Jdk与jre的区别?

Java运行是环境(jre)是将要执行java程序的java虚拟机。

Java开发工具包(jdk)是完整的java软件开发包,包含jre,编译器和其他工具如javaDoc,java调试器,可以让开发者开发,编译,执行java应用程序。


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

通常我们定义一个基本数据类型的变量,一个 对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间;而通过new关键字和构造器创建的对象放在堆空间;程序中的字面量(literal)如直 接书写的100、“hello”和常量都是放在静态存储区中。栈空间操作最快但是也很小,通常大量的对象都是放在堆空间,整个内存包括硬盘上的虚拟内存都 可以被当成堆空间来使用。

String str=new String(“hello”);

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


swtich 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?

早期的JDK中,switch(expr) 中,expr可以是byte、short、char、int。从1.5版开始,Java中引入了枚举类型(enum),expr也可以是枚举,从JDK 1.7版开始,还可以是字符串(String)。长整型(long)是不可以的。

备注:switch(expr)里面的expr参数根jdk版本有关,jdk版本不用,参数范围也不同。


当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对象的引用是永远不会改变的。


String 和StringBuilder、StringBuffer 的区别?

Java 平台提供了两种类型的字符串:String和StringBuffer / StringBuilder,它们可以储存和操作字符串。其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。而 StringBuffer和StringBuilder类表示的字符串对象可以直接进行修改。StringBuilder是JDK 1.5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修 饰,因此它的效率也比StringBuffer略高。

补充1:有一个面试题问:有没有哪种情况 用+做字符串连接比调用StringBuffer / StringBuilder对象的append方法性能更好?如果连接后得到的字符串在静态存储区中是早已存在的,那么用+做字符串连接是优于 StringBuffer / StringBuilder的append方法的。

补充2:下面也是一个面试题,问程序的输出,看看自己能不能说出正确答案。

package com.lovo;      
   public class StringEqualTest {      
       public static void main(String[] args) {      
           String a = "Programming";      
           String b = new String("Programming");      
           String c = "Program" + "ming";            
           System.out.println(a == b);//false      
           System.out.println(a == c); //true     
           System.out.println(a.equals(b));//true      
           System.out.println(a.equals(c));//true      
           System.out.println(a.intern() == b.intern()); //true     
       }      
   }      

Java 中的final关键字有哪些用法?

修饰类:表示该类不能被继承;

修饰方法:表示方法不能被重写;

修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。


指出下面程序的运行结果?  

class A{      
   static{      
      System.out.print("1");      
   }      
   public A(){      
      System.out.print("2");      
   }      
}      
class B extends A{            
    static{      
      System.out.print("a");      
    }      
    public B(){      
       System.out.print("b");      
    }      
}      
public class Hello{      
   public static void main(String[] args){      
      A ab = new B();      
      ab = new B();      
   }      
}      

答:执行结果:1a2b2b。创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。


数据类型之间的转换?

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

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

答:

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

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


sleep()和yield()有什么区别?

1.sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;

2.线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;

3.sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;

4.sleep()方法比yield()方法(跟操作系统相关)具有更好的可移植性。


当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法?

不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。


请说出与线程同步相关的方法?

1.wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;

2.sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException 异常;

3.notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;

4.notityAll():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争;

5.JDK 1.5通过Lock接口提供了显式(explicit)的锁机制,增强了灵活性以及对线程的协调。Lock接口中定义了加锁(lock())和解锁 (unlock())的方法,同时还提供了newCondition()方法来产生用于线程之间通信的Condition对象;

6.JDK 1.5还提供了信号量(semaphore)机制,信号量可以用来限制对某个共享资源进行访问的线程的数量。在对资源进行访问之前,线程必须得到信号量的 许可(调用Semaphore对象的acquire()方法);在完成对资源的访问后,线程必须向信号量归还许可(调用Semaphore对象的 release()方法)。


你在开发中都用到了那些设计模式?用在什么场合?

面试被问到关于设计模式的知识时,可以拣最常用的作答,例如:

1)工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作(多态方法)。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。

2)代理模式:给一个对象提供一个代理对象,并由代理对象控制原对象的引用。实际开发中,按照使用目的的不同,代理可以分为:远程代理、虚拟代理、保护代理、Cache代理、防火墙代理、同步化代理、智能引用代理。

3)适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起使用的类能够一起工作。

4)模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法(多态实现),从而实现不同的业务逻辑。

除此之外,还可以讲讲上面提到的门面模式、 桥梁模式、单例模式、装潢模式(Collections工具类里面的synchronizedXXX方法把一个线程不安全的容器变成线程安全容器就是对装 潢模式的应用,而Java IO里面的过滤流(有的翻译成处理流)也是应用装潢模式的经典例子)等,反正原则就是拣自己最熟悉的用得最多的作答,以免言多必失。


在进行数据库编程时,连接池有什么作用?

由于创建连接和释放连接都有很大的开销(尤 其是数据库服务器不在本地时,每次建立连接都需要进行TCP的三次握手,再加上网络延迟,造成的开销是不可忽视的),为了提升系统访问数据库的性能,可以 事先创建若干连接置于连接池中,需要时直接从连接池获取,使用结束时归还连接池而不必关闭连接,从而避免频繁创建和释放连接所造成的开销,这是典型的用空 间换取时间的策略(浪费了空间存储连接,但节省了创建和释放连接的时间)。池化技术在Java开发中是很常见的,在使用线程时创建线程池的道理与此相同。

基于Java的开源数据库连接池主要有: C3P0、Proxool、DBCP、BoneCP、Druid等。


Statement和PreparedStatement有什么区别?哪个性能更好?

与Statement相比:

①PreparedStatement接口代表预编译的语句,它主要的优势在于可以减少SQL的编译错误并增加SQL的安全性(减少SQL注射攻击的可能性);

②PreparedStatement中的SQL语句是可以带参数的;

③当批量处理SQL时或频繁执行相同的查询时,PreparedStatement有明显的性能上的优势,由于数据库可以将编译优化后的SQL语句缓存起来,下次执行相同语句时就会很快。

原文地址:https://www.cnblogs.com/qlqwjy/p/7683778.html