面试题(一)

来源:互联网 发布:淘宝的高级搜索在哪里 编辑:程序博客网 时间:2024/05/22 12:14

1、String s = new String("xyz");创建了几个StringObject?是否可以继承String类?

        两个或一个都有可能,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。NewString每写一遍,就创建一个新的对象,它使用常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,那么这里就不会创建”xyz”了,直接从缓冲区拿,这时创建了一个StringObject;但如果以前没有用过"xyz",那么此时就会创建一个对象并放入缓冲区,这种情况它创建两个对象。至于String类是否继承,答案是否定的,因为String默认final修饰,是不可继承的


2、String和StringBuffer的区别

        JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串可以进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers来动态构造字符数据。

      

3、下面这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";

对于如下代码:

String s1 = "a";

String s2 = s1 + "b";

String s3 = "a" + "b";

System.out.println(s2 == "ab");

System.out.println(s3 == "ab");

第一条语句打印的结果为false,第二条语句打印的结果为true,这说明javac编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期再去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。

题目中的第一行代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串,所以,上面的代码应该只创建了一个String对象。写如下两行代码,

          String s ="a" + "b" +"c" + "d";

          System.out.println(s== "abcd");

最终打印的结果应该为true。


4、try {}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?

        我们知道finally{}中的语句是一定会执行的,那么这个可能正常脱口而出就是return之前,return之后可能就出了这个方法了,鬼知道跑哪里去了,但更准确的应该是在return中间执行,请看下面程序代码的运行结果:

public classTest {

    public static void main(String[]args) {

       System.out.println(newTest().test());;

    }

    static int test()

    {

       intx = 1;

       try

       {

          returnx;

       }

       finally

       {

          ++x;

       }

    }

  

}

---------执行结果 ---------

运行结果是1,为什么呢?主函数调用子函数并得到结果的过程,好比主函数准备一个空罐子,当子函数要返回结果时,先把结果放在罐子里,然后再将程序逻辑返回到主函数。所谓返回,就是子函数说,我不运行了,你主函数继续运行吧,这没什么结果可言,结果是在说这话之前放进罐子里的。

5、如何线程安全的使用hashMap?

  • Hashtable
  • ConcurrentHashMap
  • SynchronizedMap
import java.util.Collections;
//HashtableMap<String, String> hashtable = new Hashtable<>(); //synchronizedMapMap<String, String> synchronizedHashMap = Collections.synchronizedMap(new HashMap<String, String>()); //ConcurrentHashMapMap<String, String> concurrentHashMap = new ConcurrentHashMap<>();
而在SynchronizedMap类中使用了synchronized同步关键字来保证对Map的操作是线程安全的。ConcurrentHashMap性能是明显优于Hashtable和SynchronizedMap的,当一个线程使用put方法时,另一个线程不但不可以使用put方法,连get方法都不可以,所以效率很低。

6、在接口里能写方法吗?
      在JDK8中,可以选择直接在接口中实现该方法。(interface已经把手伸到abstract class的地盘了)。在接口中方法声明都是public类型,但通过static和default修饰符我们可以直接在接口中实现方法体。例:
package defaultmethods;import java.time.*;public interface TimeClient {    void setTime(int hour, int minute, int second);    void setDate(int day, int month, int year);    void setDateAndTime(int day, int month, int year,                               int hour, int minute, int second);    LocalDateTime getLocalDateTime();        static ZoneId getZoneId (String zoneString) {        try {            return ZoneId.of(zoneString);        } catch (DateTimeException e) {            System.err.println("Invalid time zone: " + zoneString +                "; using default time zone instead.");            return ZoneId.systemDefault();        }    }            default ZonedDateTime getZonedDateTime(String zoneString) {        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));    }}

对于TimeClient接口中定义的getZonedDateTime方法,你可以做如下三种处理:

  1. 重新声明getZonedDateTime方法,使它变成abstract类型。
  2. 重新定义getZonedDateTime方法。
  3. 直接继承。

而static方法和我们在类里面定义的static方法概念一致。

7、如何实现redis持久化?
        Redis的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”);也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。具体详细说明:http://blog.csdn.net/freebird_lb/article/details/7778981

1、final, finally, finalize的区别。 

        final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。内部类要访问局部变量,局部变量必须定义成final类型。

        finally是异常处理语句结构的一部分,表示总是执行。

        finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。但是JVM不保证此方法总被调用


2、运行时异常与一般异常有何异同?

        异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。


3、error和exception有什么区别?

        error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。exception表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。

 

4、简单说说Java中的异常处理机制的简单原理和应用。

        异常是指java程序运行时(非编译)所发生的非正常情况或错误,与现实生活中的事件很相似,现实生活中的事件可以包含事件发生的时间、地点、人物、情节等信息,可以用一个对象来表示,Java使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象来表示的,该对象中包含有异常的信息。

        Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类:

        Error和Exception,Error表示应用程序本身无法克服和恢复的一种严重问题,程序只有奔溃了,例如,说内存溢出和线程死锁等系统问题。

        Exception表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常:

        系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件挂掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);

        普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。

java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,而系统异常可以处理也可以不处理,所以,编译器不强制用try..catch处理或用throws声明,所以系统异常也称为unchecked异常。


5、Java 中堆和栈有什么区别?
        JVM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。

        栈:在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。

        堆:堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。


6、能将 int 强制转换为 byte 类型的变量吗?如果该值大于 byte 类型的范围,将会出现什么现象? 
        我们可以做强制转换,但是 Java 中 int 是 32 位的,而 byte 是 8 位的,所以,如果强制转化,int 类型的高 24 位将会被丢弃,因为byte 类型的范围是从 -128 到 128。

7、@RequestParam, @RequestBody 区别

http://blog.csdn.net/xinluke/article/details/52710706

8、web开发的怎样解决重复提交问题

答:前端:

方案一:通过设立标识使表单不能重复提交:

方案二:一次点击后使得提交按钮变成不可用

后端:

方案一:让当前的线程睡眠3秒钟,模拟网络延迟而导致表单重复提交的现象

方案二:通过在数据库中字段设立唯一标识(即设定唯一约束)来解决,这样在进行数据库插入操作时,因为每次插入的数据都相同,数据库会拒绝写入。这样也避免了向数据库中写入垃圾数据的情况,同时也解决了表单重复提交问题。只适用于某系特定的插入操作。

方案三:把标记放在session中,可以!      

  1> 在原表单页面,生成一个随机值 token    

  2> 在原表单页面,把token值放入session 属性中        

  3> 在元表单页面,把token值放入到隐藏域中。        

  4> 在目标的Servlet 中:获取session 和隐藏域中的token值        

  5> 比较两个值是否一致:若一致,受理请求,且把session域中的token属性清除        

  6> 若不一致,则直接响应提示页面:"重复提交"




9、maven scope含义的说明

compile (编译范围【默认的】)、provided (已提供范围)、runtime (运行时范围)、test (测试范围)、system (系统范围)

10、对线程monitor的理解

它内置与每一个Object对象中,相当于一个许可证。拿到许可证即可以进行操作,没有拿到则需要阻塞等待。

 syncrhoized又叫做内置锁,为什么呢?因为使用syncrhoized加锁的同步代码块在字节码引擎中执行时,其实是通过锁对象的monitor的取用与释放来实现的。由上面我们直到Monitor是内置于任何一个对象中的,syncrhoized利用monitor来实现加锁解锁,故syncrhoized又叫做内置锁。

       现在我们知道为什么用syncrhoized(lock)来加锁时,锁对象可以是任意对象了:

       1:syncrhoized(lock)加锁时,用到的其实只是lock对象内置的monitor而已;

       2:一个对象的monitor是唯一的,相当于一个唯一的许可证。拿到许可证的线程才可以执行,执行完后释放对象的monitor才可以被其他线程获取。http://www.cnblogs.com/ygj0930/p/6561667.html      http://blog.csdn.net/hqq2023623/article/details/51000153

11、Java高并发,如何解决,什么方式解决

答:一般加对象锁同步关键字synchronized,但性能大大降低,可以用乐观锁机制。详见:http://www.cnblogs.com/lr393993507/p/5909804.html

12、spring两种动态代理方式是:

        JDK动态代理和CGLIB动态代理

JDK内置的Proxy动态代理可以在运行时动态生成字节码,而没必要针对每个类编写代理类。中间主要使用到了一个接口InvocationHandler与Proxy.newProxyInstance静态方法,参数说明如下:

 使用内置的Proxy实现动态代理有一个问题:被代理的类必须实现接口,未实现接口则没办法完成动态代理。

如果项目中有些类没有实现接口,则不应该为了实现动态代理而刻意去抽出一些没有实例意义的接口,通过cglib可以解决该问题。

13、MySql大数据量分页性能优化

例:select * from product limit 866613, 20   37.44秒,利用了索引查询的语句中如果只包含了那个索引列(覆盖索引),那么这种情况会查询很快,如果id字段是主键,自然就包含了默认的主键索引。现在让我们看看利用覆盖索引的查询:select id from product limit 866613, 20 0.2秒

那么如果我们也要查询所有列,有两种方法,一种是id>=的形式,另一种就是利用join,看下实际情况:

SELECT * FROM product WHERE ID > =(select id from product limit 866613, 1) limit 20
查询时间为0.2秒,简直是一个质的飞跃啊,哈哈

另一种写法
SELECT * FROM product a JOIN (select id from product limit 866613, 20) b ON a.ID = b.id
查询时间也很短,赞!

14、oracle物理存储结构是怎样的

Oracle常用的有两种索引类型:B树索引(默认索引类型)和位图索引。正是由于B树索引的结构特点,Oracle 数据库中的B树索引有以下优势:

1.所有的索引叶子块都在同一层,他们索引深度是相同的。这意味着访问索引叶子块的任何一个索引键值所花费的时间几乎相同。

2.Oracle能保证所有的B树索引是自平衡的,不可能出现不同的索引叶子块处于同一层的现象。

3.通过B树索引访问表里行记录的效率不会随着相关表的数据量的递增而明显降低。


http://www.cnblogs.com/vincently/p/4526560.html


15、redis 的两种持久化方式及原理


1.Redis的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”):默认redis是会以快照的形式将数据持久化到磁盘的(一个二进 制文件,dump.rdb,这个文件名字可以指定),在配置文件中的格式是:save N M表示在N秒之内,redis至少发生M次修改则redis抓快照到磁盘。当然我们也可以手动执行save或者bgsave(异步)做快照。

2.把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”):filesnapshotting方法在redis异常死掉时, 最近的数据会丢失(丢失数据的多少视你save策略的配置),所以这是它最大的缺点,当业务量很大时,丢失的数据是很多的。Append-only方法可 以做到全部数据不丢失,但redis的性能就要差些。AOF就可以做到全程持久化,只需要在配置文件中开启(默认是no),appendonly yes开启AOF之后,redis每执行一个修改数据的命令,都会把它添加到aof文件中,当redis重启时,将会读取AOF文件进行“重放”以恢复到 redis关闭前的最后时刻。

16、spring事物有哪些传播特性

     1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启
     2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
     3. PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
     4. PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
     5. PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
     6. PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常
     7. PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 
      则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行

17、Spring事务的隔离级别
      1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
      另外四个与JDBC的隔离级别相对应
      2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
      这种隔离级别会产生脏读,不可重复读和幻像读。
     3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
     4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
      它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
     5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
      除了防止脏读,不可重复读外,还避免了幻像读。 

18、Spring中Bean的五个作用域

  • singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例

  • prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例

  • request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效

  • session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效

  • globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效

19、session和客户端是如何会话的
服务端为他们之间的会话创建一个session对象。并生成一个唯一sessionId(JSessionId)返回给客户端的Cookie中,这个JsessionId对应于服务端创建的session对象,之后客户端每次向服务端发送请求携带着JsessionId对象,服务端通过JsessionId来找到对应的session对象使用。若客户端没有携带JsessionId,则创建一个session并且生成一个于此相关联的JSessionId来返回客户端。

  当某个用户向Web服务器发出请求时,服务器首先会检查这个客户端的请求里是否已经包含了一个Session ID。如果包含,说明之前已经为此用户创建过Session,服务器则按该Session ID把Session检索出来使用。如果客户端请求不包含Session ID,则为该用户创建一个Session,并且生成一个与此Session相关联的Session ID,在本次响应中被传送给客户端保存。详细:http://blog.csdn.net/shiyaru1314/article/details/70142353
















原创粉丝点击