Android校招复习全书(1)-j2se

一、九种基本数据类型的大小,以及他们的封装类

关于JAVA基本数据类型

名称解释长度(位)默认值封装类
byte字节80Byte
shot短整型160Short
int整型320Integer
long长整型640Long
float浮点型320.0fFloat
double双精度640.0dDouble
char字符型16‘\u0000’Character
boolean布尔型1falseBoolean
void

操作系统16位的时候,int 2字节,操作系统32位的时候,int 4字节,由于32位系统之前占主流地位,实际现在就算是64位系统,出于兼容性考虑,int也是4字节的。
Java的类型分成两种,一种是基本类型,一种是引用类型。两种的本质区别就是:基本类型是在堆栈处分配空间存“值”。但是引用类型,是在堆里面分配空间存“值”。Void是不能new出来,也就是不能在堆里面分配空间存对应的值。那就是一开始在堆栈处分配好空间了。所以,有些人将Void归成基本类型,也有道理。

二、Switch能否用string做参数?

  • JDK1.7之前不能用,JDK1.7后可以用。
  • switch后面的括号里面只能放int类型的值,但由于byte,short,char类型,它们会 自动 转换为int类型(精精度小的向大的转化),所以它们也支持。
  • 我们也可以用枚举类型实现switch可传入string参数。

三、equals与==的区别

前者比较值,后者比较在内存中地址的位置。
String比较特殊重写了equals方法

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

如果自定义的类重写了equals值,用于比较值相同,一定要重写hashcode方法,因为在HashSet/HashMap/HashTable进行查重比较的时候,用于hashcode

四、Object有哪些公用方法?

1.protected Object clone()创建并返回此对象的一个副本。
1)浅复制和深复制的概念
 浅复制:被复制的对象的所有变量都与原来的对象有相同的值,但是指向的引用的对象相同,即地址相同,操作一个对象,另一个也会改变。
 深复制:被复制的对象的所有变量都与原来的对象有相同的值,但是复制了引用的对象不相同,即地址不同,操作一个对象,另一个不会改变。
2)Java的clone()方法
package com.li;
public class Test4
{
    public static void main(String[] args)
    {
        // TODO Auto-generated method stub
        Student s1 = new Student("zhangsan", 12);
        Student s2 = (Student) s1.clone();
        s2.name="lisi";    
        s2.age=20;   
        System.out.println("name="+s1.name+","+"age="+s1.age);//   name=zhangsan,age=12
    }
}

class Student implements Cloneable
{
    String name;    
    int age;    
    Student(String name,int age)    
    {    
       this.name=name;    
       this.age=age;    
    }    

    @Override
    protected Object clone()
    {
        Object o = null;
        try
        {
            o = (Student)super.clone();
            return o;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return o;
    }
}

①为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。
②继承自java.lang.Object类的clone()方法是浅复制。以下代码可以证明之。

package com.li;

public class Test4
{
    public static void main(String[] args)
    {
        // TODO Auto-generated method stub
        Professor p = new Professor("jiaoshou",50);
        Student s1 = new Student("li", 20, p);
        Student s2 = (Student) s1.clone();
        s2.p.name = "jiaoshou2";
        s2.p.age = 55;
        //如果加了注释输出:name=jiaoshou2,age=55
        System.out.println("name="+s1.p.name+","+"age="+s1.p.age);
        //如果不加注释输出:name=jiaoshou,age=50
    }
}

class Professor implements Cloneable
{
    String name;
    int age;
    public Professor(String name, int age)
    {
        this.name = name;
        this.age = age;
    }
    /*
    @Override
    protected Object clone()
    {
        Professor o = null;
        try
        {
            o = (Professor) super.clone();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return o;
    }*/
}

class Student implements Cloneable
{
    String name;
    int age;
    Professor p;
    public Student(String name, int age, Professor p)
    {
        this.name=name;    
        this.age=age;    
        this.p=p; 
    }

    @Override
    protected Object clone()
    {
        Student o = null;
        try
        {
            o = (Student) super.clone();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        /*o.p = (Professor) p.clone();*/
        return o;
    }
}
2. boolean equals(Object obj)指示其他某个对象是否与此对象“相等”。
3. protected void finalize()当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

C++析构函数和Java的finalize()方法不一样。前者是在对象消亡时运行,如果是自己new,即在堆中申请的内存,需要自己手动delete,所以析构函数中经常做一些文件保存之类的收尾工作;后者在Java中很不幸,如果内存总是充足的,那么垃圾回收可能永远不会进行,也就是说filalize()可能永远不被执行,显然指望它做收尾工作是靠不住的,它最主要的用途是回收特殊渠道申请的内存。Java程序有垃圾回收器,所以一般情况下内存问题不用程序员操心。但有一种JNI(Java Native Interface)调用non-Java程序(C或C++),finalize()的工作就是回收这部分的内存。

4. Class getClass() 返回此 Object 的运行时类。
5. int hashCode() 返回该对象的哈希码值。
6. void notify() 唤醒在此对象监视器上等待的单个线程。
7. void notifyAll() 唤醒在此对象监视器上等待的所有线程。
8. String toString() 返回该对象的字符串表示。
public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
9. void wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
10. void wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。
11. void wait(long timeout, int nanos) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。
//以纳秒为单位进行精确控制
public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
    }

五、Java的四种引用,强软弱虚,用到的场景。

1.强引用

以前我们使用的大部分引用实际上都是强引用,这是使用最普遍的引用。如果一个对象具有强应用,那就类似必不可少的生活用品,垃圾回收器绝不会回收它。当内存空间不足,jvm宁愿跑出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

2.软引用(SoftReference)

如果一个对象具有软引用,类似与生活可有可无的生活用品。如果内存足,GC就不会回收,如果不足,GC就会回收。软引用可以用来实现内存敏感的高速缓存。软引用可以和一个引用队列联合使用,如果软引用所引用的对象被GC回收,JVM就会把这个软引用加入到与之关联的引用队列中。

3.弱引用(WeakReference)

如果一个对象具有软引用,类似与生活可有可无的生活用品。与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在GC线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存足够与否,都会回收它的内存。不过,由于GC是个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用可以和一个引用队列联合使用,如果弱引用所引用的对象被GC回收,JVM就会把这个弱引用加入到与之关联的引用队列中。

4.虚引用(PhantomReference)

如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用以及弱引用的区别在于:虚引用必须和引用队列联合使用。当GC准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

package com.li;
import java.lang.ref.SoftReference;

//软引用实例代码
public class Test4
{
    public static void main(String[] args)
    {
        A a = new A();
        SoftReference<A> sr = new SoftReference<A>(a);
        a = null;
        if(sr != null)
        {    
            a = sr.get();
        }
        else
        {
            a = new A();
            sr = new SoftReference<A>(a);
        }
    }
}
class A{
    int[] a ;
    public A(){
        a = new int[100000000];
    }
}

六、Hashcode的作用。

  • hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;
  • 如果两个对象相同,就是适用于equals(java.lang.Object) 方法,那么这两个对象的hashCode一定要相同;
  • 如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致,否则就会违反上面提到的第2点;
  • 两个对象的hashCode相同,并不一定表示两个对象就相同,也就是不一定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”。
  • 以下代码证明,先比较hash,如果hash相同比较equals。自己敲一遍,事半功倍。
package com.li;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

public class Test6
{
    public static void main(String[] args)
    {
        Test6 a = new Test6();
        a.SetI(1);
        Test6 b = new Test6();
        b.SetI(1);
        Set<Test6> set = new HashSet<Test6>();
        set.add(a);
        System.out.println("----------");
        set.add(b);
        System.out.println("----------");
        System.out.println(set.toString());//默认调用toString方法,toString()源码调用了hashCode()
        /*输出
        hashcode
        ----------
        hashcode
        equlas
        ----------
        hashcode
        [com.li.Test6@1]
        */
    }
    public int i;

    public int getI()
    {
        return i;
    } 
    public void SetI(int i)
    {
        this.i = i;
    }
    public int hashCode()
    {
        System.out.println("hashcode");
        return i%10;   
    }
    public boolean equals(Object object) {  
        System.out.println("equlas");
        if (object == null) {  
            return false;  
        }  
        if (object == this) {  
            return true;  
        }  
        if (!(object instanceof Test6)) {  
            return false;  
        }  
        Test6 other = (Test6) object;  
        if (other.getI() == this.getI()) {  
            return true;  
        }  
        return false;  
    }
}

七、ArrayList、LinkedList、Vector的区别。

1.ArrayList

以下代码来自1.8Jdk的ArrayList.java源码

    /**
     * Default initial capacity.
     * 默认数组初始容量大小为10
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * The size of the ArrayList (the number of elements it contains).
     * 数组里面实际元素的个数
     * @serial
     */
    private int size;

    /**
     * 最大容量
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
    * 记录操作次数,快速失败机制,在迭代器中使用,remove抛出异常
    */
    protected transient int modCount = 0;

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!增加一个
        elementData[size++] = e;
        return true;
    }

    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    /**
    * 实现自增的核心代码,1.5倍递增
    */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
2.Vector

以下代码来自1.8Jdk的Vector.java源码

    /**
    * 实现自增的核心代码,2.0倍递增
    */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    /**
    * 主要区别,使用了synchronized修饰,线程安全
    */
    public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }
3.LinkedList

以下代码来自1.8Jdk的LinkedList.java源码

    /**
    * 私有内部类。用于链表操作
    */
    private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

总:
时间复杂度:ArrayList、Vector都为动态数组,LinkedList为链表。前者适合查找,后者适合修改删除。
空间复杂度:ArrayList开辟1.5倍、Vector开辟2.0倍,LinkedList每增加一个多一个内部类对象。前两者可以使用trimToSize()方法将多余的空间删除。
线程安全性:ArrayList、LinkedList不安全,但是可以自己实现线程安全。Vector线程安全。

八、String、StringBuffer与StringBuilder的区别。

String使用+""会创建一个新的对象,StringBuffer是线程安全的,使用append在一个对象进行修改,StringBuilder是1.5之后出现的,和StringBuffer基本一样,只是它不是线程安全的。

九、Map、Set、List、Queue、Stack的特点与用法。

十、HashMap和HashTable的区别。

  • 前者是线程非安全的,并能传递null作为键值对。内部维护了一个链表,通过数组和链表进行存储
  • 后者是线程安全的,不能传递null作为键值对。
  • 参考:http://www.importnew.com/7099.html

十一、HashMap和ConcurrentHashMap的区别,HashMap的底层源码。

以下是Jdk1.8的HashMap.java源码

    /**默认大小16
     * The default initial capacity - MUST be a power of two.
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    /**最大容量 <= 1<<30
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**默认装载因子
     * The load factor used when none specified in constructor.
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

十二、 TreeMap、HashMap、LindedHashMap的区别。

十三、Collection包结构,与Collections的区别。

十四、try catch finally,try里有return,finally还执行么?

public class HelloJ {
    public static void  main(String[] args)
    {
        int i = g();
        System.out.println(i);
        /*输出
          ---
          1
        */
    }
    static int g(){
        int i = 0;
        try{
            return i++;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println("---");
            return i++;
        }
    }
}

十五、Excption与Error包结构。OOM你遇到过哪些情况,SOF你遇到过哪些情况。

参考:http://www.mamicode.com/info-detail-1091344.html
这里写图片描述

十六、Java面向对象的三个特征与含义。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值