Android面试(六)JAVA

来源:互联网 发布:变声器玩游戏知乎 编辑:程序博客网 时间:2024/06/05 21:18

List,Set,Map的区别与实现?

Set 接口继承 Collection,但不允许重复,使用自己内部的一个排列机制。

List 接口继承 Collection,允许重复,以元素安插的次序来放置元素,不会重新排列。

Map接口是一组成对的键-值对象,即所持有的是key-value pairs。Map中不能有重复的key。

List的子类有哪些?请分别说出他们的不同?

ArrayList:是List的主要实现类;线程不安全,查找效率高;底层使用Object[]存储

Vector:是List的古老实现类;线程安全,效率低;底层使用Object[]存储

LinkedList:底层使用双向链表存储;对于频繁的插入、删除操作,使用此类效率高。

HashMap的实现原理

  • HashMap的底层主要是基于数组和链表来实现的,它之所以有相当快的查询速度主要是因为它是通过计算散列码来决定存储的位置。

  • HashMap中主要是通过key的hashCode来计算hash值的,只要hashCode相同,计算出来的hash值就一样。

  • 如果存储的对象对多了,就有可能不同的对象所算出来的hash值是相同的,这就出现了所谓的hash冲突。解决hash冲突的方法有很多,HashMap底层是通过链表来解决hash冲突的。

  • 系统默认负载因子为0.75,一般情况下我们是无需修改的。当哈希表中的条目数超出了加载因子与当前容
    量的乘积时,通过调用 rehash 方法将容量翻倍。

HashMap和HashTable的区别?

1.两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全

2.HashMap可以使用null作为key,而Hashtable则不允许null作为key

3.HashMap是对Map接口的实现,HashTable实现了Map接口和Dictionary抽象类
HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75

4.HashMap扩容时是当前容量翻倍即:capacity*2,Hashtable扩容时是容量翻倍+1即:capacity*2+1

5.两者计算hash的方法不同
Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模

说说&和&&的区别?

& 与 && 的区别:

&:不管左边是true还是false,右端都会进行运算。

&&:当左端为false时,右端不再进行运算以后使用时,建议使用 &&

“==”和equals方法究竟有什么区别?

==:运算符,适合于基本数据类型和引用数据类型。如果是基本数据类型,比较两个变量的值是否相等。如果是引用数据类型变量,判断两个变量是否指向内存中的同一个对象。

equals():是Object类中定义过的一个方法。只适用于对象来调用。如果各个对象所在的类没有重写Object中的equals(),则与==使用相同。如果所在的类重写了equals(),一般重写的规则是判断两个对象中包含的所有属性的值是否相等。

Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

Math.round(11.5)=12.

Math.round(-11.5)=-11.

判断方式见API:不管是正数还是负数,都需要先+0.5,然后截断取整数值。

String s = new String(“xyz”);创建了几个String Object? 二者之间有什么区别?

如果之前在字符串常量池中没现成的“xyz”可用,那么上述操作在内存中创建了两个对象。

一个是new String()对象本身,另一个是字符串常量池中生成的“xyz”。前者指向后者

final, finally,finalize()的区别?

final:关键字,表示最终的。
final可以修饰 类,成员变量(属性和方法),局部变量,

被final修饰的类,不能被继承,

被final修饰的方法,不能被重写,

被final修饰的全局变量,只能声明时显示赋值(或通过构造函数显示赋值),一但赋值就不能改变,成为常量。

被final修饰的局部变量,标记的局部变量可以只声明不赋值,然后再进行一次性的赋值,赋值后不可以改变。

finally:关键字,在异常处理机制中可以使用try-catch-finally进行异常的处理。finally中存放的是一定会被执行的代码。比如:流的关闭、Socket的关闭、数据连接的关闭。

finalize():在Object中定义的方法,用于在垃圾回收时,显示的调用垃圾收集器回收垃圾

是否可以在static环境中访问非static变量?

不能。因为static声明的结构随着类的加载而加载,生命周期早于非static的变量。
反之,在非static的环境中,是可以访问早加载的static的变量的。

内部类访问外部属性为什么加final?

首先,内部类和外部类其实是处于同一个级别,内部类不会因为定义在方法中就会随着方法的执行完毕而跟随者被销毁。如果外部类的方法中的变量不定义final,那么当外部类方法执行完毕的时候,这个局部变量肯定也就被GC了,然而内部类的某个方法还没有执行完,这个时候他所引用的外部变量已经找不到了。如果定义为final,java会将这个变量复制一份作为成员变量内置于内部类中,这样的话,由于final所修饰的值始终无法改变,所以这个变量所指向的内存区域就不会变。

在局部内部类中局部变量,被final修饰后,生命周期变长,当方法结束后,变量依然存在,所以内部类可以访问fianl修饰的变量;

原理:每个内部类对象拷贝了被final修饰的变量的值。(参考网上)这样即使方法没有了,变量依然可以调用变量。

当final修饰对象时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。

写出你知道的设计模式?并谈谈项目中的使用

问题一:单例模式、工厂方法、抽象工厂、代理模式、模板方法、观察者、适配器

单例模式:如果整个应用只需要对一个类只产生一个对象的时候,就可以使用单例(工具类,第三方)

说说如何实现断点下载?

1 利用URLConnection获取要下载文件的长度、头部等相关信息,并设置响应的头部信息。
并且通过URLConnection获取输入流,将文件分成指定的块,每一块单独开辟一个线程完成数据的读取、写入。

2 通过输入流读取下载文件的信息,然后将读取的信息用RandomAccessFile随机写入到本地文件中。同时,每个线程写入的数据都文件指针也就是写入数据的长度,需要保存在一个临时文件中。

3 这样当本次下载没有完成的时候,下次下载的时候就从这个文件中读取上一次下载的文件长度,然后继续接着上一次的位置开始下载。并且将本次下载的长度写入到这个文件中。

单例在多线程中的运行问题?

单例分为饿汉式和懒汉式,如果在多线程中调用单例模式,获取对象的时候,如果使用的是饿汉式,不存在线程的安全问题。如果是懒汉式,那就存在线程的安全问题,需要使用同步进行处理。

请简述final关键字

被final修饰的类,不能被继承,

被final修饰的方法,不能被重写,

被final修饰的全局变量,只能声明时显示赋值(或通过构造函数显示赋值),一但赋值就不能改变,成为常量。

被final修饰的局部变量,标记的局部变量可以只声明不赋值,然后再进行一次性的赋值,赋值后不可以改变。

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

1.sleep()定义在Thread类里,wait()定义在Object类里

2.不同之处在于解除阻塞的时机不同。sleep()指定的事件结束后,解除阻塞。wait()是显式的由其它线程调用了notify()/notifyAll()之后,解除阻塞。

3.wait()必须使用在同步中,而sleep()没这样的要求。如果都使用在同步中的话,sleep()不会释放锁,而wait()会释放锁。

线程池有几种?分别是什么?

newCachedThreadPool()缓存型池子,先查看池中没以前建立的线程,如果有就 reuse 如果没有,就建一个新的线程加入池中缓存型池子通常用于执行一些生存期很短的异步型任务 因此在一些面向连接的 daemon 型 SERVER 中用得不多。但对于生存期短的异步任务,它是 Executor 的首选。
能 reuse 的线程,必须是 timeout IDLE 内的池中线程,缺省 timeout 是 60s,超过这个 IDLE 时长,线程实例将被终止及移出池。注意,放入 CachedThreadPool 的线程不必担心其结束,超过 TIMEOUT 不活动,其会自动被终止。

**newFixedThreadPool(int)**newFixedThreadPool 与 cacheThreadPool 差不多,也是能 reuse 就用,但不能随时建新的线程。其独特之处:任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子。和 cacheThreadPool 不同FixedThreadPool 多数针对一些很稳定很固定的正规并发线程,多用于服务器。从方法的源代码看,cache池和fixed 池调用的是同一个底层 池,只不过参数不同

newScheduledThreadPool(int)
调度型线程池
这个池子里的线程可以 schedule 依次 delay 执行,或周期执行

SingleThreadExecutor()
单例线程,任意时间池中只能一个线程
用的是和 cache 池和 fixed 池相同的底层池

StringBuilder和StringBuffer的区别?

StringBuffer是可变类,任何对它所指代的字符串的改变都不会产生新的对象。StringBufferd支持并发操作,线性安全的,适合多线程中使用。

StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用。但其在单线程中的性能比StringBuffer高。

Integer对象比较?

    Integer a = 10;    Integer dInteger = 10;    System.out.println(a == dInteger);//true    Integer b = 200;    Integer c = 200;    System.out.println(b == c);//false    //byte short int long 全部是有缓存的-128 127    //debug跟踪到的系统代码    public static Integer valueOf(int i) {    if (i >= IntegerCache.low && i <= IntegerCache.high)        return IntegerCache.cache[i + (-IntegerCache.low)];    return new Integer(i);    }

java中可以自定义类覆盖系统的类吗(全类名一致)?

不能

1 自定义的包不能以 Java.xxx.xx 开头,这是一种安全机制,如果以java开头,则直接异常

2 Java在加载类时,采用的是代理模式,即,类加载器在尝试自己去查找某个类的字节代码并定义它时,会先代理给其父类加载器,由父类加载器先去尝试加载这个类

3 Java虚拟机不仅要看类的全名是否相同,还要看加载此类的类加载器是否一样。只有两者都相同,才认为两个类时相同的

4 Java中的类加载器大致可以分为两类 : 一类是系统提供的,一类则是由Java应用开发人员编写的。

引导类加载器 (bootstrap class loader):它用来加载Java的核心库,是用原生代码实现的,并不继承自java.lang.ClassLoader。

扩展类加载器 (extensions class loader):它用来加载Java的扩展库。Java虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载Java类。

系统类加载器 (system class loader):它根据Java应用的类路径(CLASSPATH)来加载Java类。一般来说,Java应用的类都是由它来完成加载的。可以通ClassLoader.getSystemClassLoader()来或其它。开发人员可以通过继承java.lang.ClassLoader类的方式实现自己的类加载器