java 面试1

1,原生的char支不支持中文字符,为什么

   答:char类型变量是用来Unicode编码的字符,Unicode编码字符集中包含了汉字,所以char型变量支持存储汉字,同时char类型占2个字节,unicode编码占用两个字节。

2.覆盖equals需要注意的事项

   答:在object文档中我们可以发现,equals指示其他某个对象是否与此对象相等,equals方法在非空对象引用上实现相等关系。

     (1) 自反性:对于任何非空引用值x,x.equals(x)都应该返回true.

     (2)对称性:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应该返回true。

     (3)传递性:对于任何非空引用值x.y.z,如果x.equals(y)返回true是,并且y.equals(z)返回ture,那么x.equals(z)应返回true。

     (4)一致性:对于任何非空引用值x和y,多次调用x.equals(y)始终返回true或始终返回false,前提是对象上equals比较中所用的信息没有修改。

      (5)对于任何非空引用值x,x.equals(null)都应返回false。

   注意:当此方法被重写时,通常有必要重写hashcode方法,以维护hashcode方法的常规协定,该协定声明相等对象必须具备相等的哈希吗。

3.synchronized和lock的区别和所用,什么时候synchronized是对象锁

答:前提了解锁:我们从jvm的角度来看一看锁的概念,java程序在运行环境中,jvm需要对两类线程共享的数据进行协调,

    (1) 保存在堆中的实例变量

    (2)保存在方法区中的类变量

这两类数据是被所有线程共享的。接下来就是java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。线程进入同步代码块或方法的时候会自动获取该锁,在退出代码块或方法时会释放该锁,获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。

       java的内置锁是一个互斥锁,这就意味着最多只有一个线程能够获得该锁,当线程A尝试去获取线程B持有的内置锁时,线程A必须等待或者阻塞,直到线程B释放锁。java的对象锁:用于对象实例方法,或者一个对象实例上。java的类锁:用于类的静态方法或者一个类的class对象。

synchronized(关键字)的使用及原理:

    synchronize的三种应用方式:

(1)修饰实例方法,作用于当前实例加锁,进入同步代码前要获取当前实例的锁。

(2)修饰静态方法,作用于当前类对象加锁,进入同步代码前需要获得当前类对象的锁。多个线程分别访问实例对象的非static syschronized方法和static syschronized方法,是不会发生互斥情况,因为static syschronized方法占用的锁是当前类的class对象锁,而非static synchronize方法占用的锁是当前实例对象锁。

  (3)  修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码前需要获取给定对象的锁。

Lock使用及原理:

synchronized与lock的区别

(1)类型不同

      synchronized是关键字,是jvm层面的实现,java的内置特性,lock是一个接口,是jdk层面的实现。

(2)获取锁和释放锁的方式不同

synchronized是jvm实现的,锁的获取和释放是不可见的,当发生异常时,锁的释放有jvm实现。

lock接口中提供的方法,可以让编程人员更加方便的实现锁的各种操作,比如尝试获取锁的,设置锁的超时时间,中断等待等,lock在编码中进行锁的操作,需要自动调用接口中的方法释放锁,所以使用lock是需要配合try模块,在finally中释放锁,不然一旦发生异常可能会在造成死锁现象。

   (3) 锁的状态和锁的类型

synchronized无法判断锁的状态,lock接口可以获取锁,同时判断锁的状态。

synchronized属于可重入,不可中断,非公平锁类型,lock属于可重入,可判断,可公平锁类型。

(4)性能上

synchronized实现少量同步,在jdk1.5中,synchronize性能是抵效的,因为这是一个重量级操作,他对性能最大的影响是阻塞的实现,挂起线程和恢复线程的操作都需要转入内核态中完成,这些给操作系统带来很大的压力。但是到了jdk1.6,官方对synchronized加入很多优化措施,有自适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等,导致jdk1.6synchronized的性能并不比lock差,官方提倡使用synchronized来进行同步。

lock实现大量同步。

顺便浅析一下两种锁机制的底层实现策略:

互斥同步最主要的问题是线程挂起和唤醒所带来的性能问题,这种同步称为阻塞同步,属于悲观的并发策略,即线程获得的是独占锁,独占锁意味着其他线程只能依靠阻塞来等待线程释放锁,而在cpu转换线程阻塞是会引起线程上下文切换,当很多线程竞争锁的时候,会引起cpu频繁的上下文切换导致效率很低,synchronized采用的就是这种策略。

随着指令集的发展,我们有了另一种选择:基于冲突检测的乐观并发策略,通俗来讲即先进性操作,如果没有其他线程使用共享数据的话,那操作成功,如果共享数据被征用,产生了冲突,那就在进行其他的补偿操作(比如不断重拾),这种乐观的并发策略的许多伤心爱你都不需要把线程挂起,称为非阻塞同步,ReetrantLock采用的便是这种并发策略。

4.怎么遍历集合删除元素

答:使用迭代器Iterator遍历集合在删除。

 ArrayList<String> a = new ArrayList<String>();
      a.add("aaaa");
      a.add("bbbb");
      a.add("cccc");
      
//      for(int i=0;i<a.size();i++) {
//          if(a.get(i)=="aaaa" && a.get(i).equals("aaaa")) {
//              System.out.println(a.get(i));
//              a.remove(a.get(i));
//          }
//      }
//      System.out.println(a);
      
      Iterator<String> is = a.iterator();
      while(is.hasNext()) {
          if(is.next().equals("cccc")) {
              is.remove();
          }
      }
      System.out.println(a);
  }

5.为什么string要设计成不可变的

答:首先我们看源码知道String底层是由char数组构成,而且还是private final 修饰,我们在创建一个字符串对象时,其实是将字符串保存在char数组中,因为数组是引用对象,为了防止数组可变,jdk添加了final修饰,加了final修饰的数组只是代表了引用不可变,不代表数组的内容不可变,因此又添加了private修饰符。

注:部分答案来自其他博客的引用,具体实在记不清了,望勿见怪

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值