美文网首页
java随笔

java随笔

作者: 尘封_12d3 | 来源:发表于2017-06-01 23:57 被阅读0次

    static变量和static方法

    static变量

    1.static修饰的变量:静态变量,静态变量在内存中只有一个拷贝,jvm只为静态变量分配一次内存,在加载类的过程中完成静态变量的内存分配。可以类名直接访问。一般在对象之间共享值时和方便访问变量时使用静态变量。

    2.实例变量,每创建一个实例就会为实例变量分配一次内存,实例变量可以有多个拷贝,互不影响。

    静态方法

    静态方法可以直接通过类名调用,实例也可调用。静态方法中不能使用this和super关键字,不能直接访问所属类的实例变量和实例方法,只能访问所属类的静态成员变量和成员方法。

    static代码块

        public class Test5 {    
        private static int a;    
        private int b;    
         
        static{    
        Test5.a=3;    
        System.out.println(a);    
        Test5 t=new Test5();    
        t.f();    
        t.b=1000;    
        System.out.println(t.b);    
        }
    

    在类中独立于类成员的static语句块,可以有多个,jvm加载类时会按顺序执行静态代码块

    static final

    static final修饰的变量,表示一旦赋值就不可修改,并且可以通过类名访问
    static final修饰的方法,不可覆盖,可通过类名直接访问

    java支持的数据类型有?何为自动拆装箱?

    1.byte

    2.short

    3.int

    4.long

    5.float

    6.double

    7.boolean

    8.char
    自动装箱时java编译器在基本数据类型和对应的对象包装类型之间做的一个转化,比如int转成Integer,double转double等,反之就是自动拆箱

    java不支持多继承。每个类只能继承一个类,但可以实现多个接口

    抽象类和抽象接口

    java提供和创建抽象类和接口,不同点
    1.接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。

    2.类可以实现很多个接口,但是只能继承一个抽象类

    3.类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。

    4.抽象类可以在不提供接口方法实现的情况下实现接口。

    5.Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。

    6.Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。

    7。接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。

    创建线程的几种方式*

    1. 继承thread类
    2. 实现Runnable接口
    3. 使用Executor框架来创建线程池
      java不支持多继承,实现接口的方式更受欢迎

    synchronized获取锁,同步*

    在监视器内部,如何做线程同步?程序应做何种级别的同步

    监视器和锁在Java虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器

    hashMap的原理

    hashMap以key-value的形式进行数据存储,本质上是数组和链表的结合。

    initialCapacity(初始容量)和loadFactor(加载因子)是影响hashMap性能的重要参数。默认初始容量16,加载因子是0.75。为了保证HashMap的效率,系统必须要在某个临界点进行扩容处理,临界点:当HashMap中元素的数量=数据长度length*加载因子(loadFactor).扩容是一个非常耗时的过程,需要重新计算数据在数组中的位置并进行复制。

    实验表明length=2的n次方时,数组中元素分布较均匀
    过程:

    1. 利用key的hashCode重新hash计算出当前对象的元素在数组中的下标,然后找到在数组中的位置。
    2. 如果hash值相同且key值也相同,则覆盖原始值;如果hash相同key不同(出现冲突),则将当前的key-value放入链表中

    hashMap和hashTable、ConcurrentHashMap和synchronized Map的原理和区别(出处:http://www.importnew.com/21396.html

    HashMap中key可以为null,HashTable中key不可以为null,ConcurrentHashMap中key和value都不能为null
    HashMap是非线程安全的
    如何线程安全的使用hashMap
    Map<String,String> hashTable = new HashTable<String,String>()
    Map<String,String> synchronizedMap = Collections.synchronizedMap(new HashMap<String,String>)
    Map<String,String> concurrentHashMap = new ConcurrentHashMap<String,String>();
    HashMap何时会产生死循环?

    HashTable

    HashTable源码中使用synchronized来保证线程安全,如get方法和put方法
    public synchronized V get(Object key){
    //省略
    }
    public synchronized V put(Object key){
    //省略
    }
    当一个线程使用put方法时别的线程不但不可以使用put,连get方法都不可以使用,效率低!现已基本不使用

    ConcurrentHashMap

    ConcurrentHashMap线程安全的,适用于读者数量大于写者数量的场景

    1. 允许并发读和线程安全的更新操作
    2. 在执行写操作时,只锁住部分map
    3. 高的并发级别会造成时间和空间的浪费,低的并发级别在写线程多时会引起线程间的竞争
    4. 返回的迭代器是弱一致性,fail-safe并且不会抛出ConcurrentModificationException异常
    5. 不允许null的键值
    6. 可代替HashTable,但CHM不会锁住整个map
    java7

    采用锁分离技术,使用多个锁来控制hash表的不同部分,每一部分相当于一个hashTable,有自己的锁。只要多个修改操作发生在不同的segment上,就可以并发执行。
    有些方法需要跨段,如size()和containsValue(),他们可能需要锁定整个表而不仅仅是段,这需要按顺序锁定所有段,操作完毕后,按顺序释放所有段的锁

    java8
    synchronizedHashMap

    源码
    //synchronizedMap方法
    public static <K,V> Map<K,V>synchronizedMap(Map<K,V> m){
    return new SynchronizedMap<>(m);
    }
    //SynchronizedMap类
    private static class SynchronizedMap<K,V> implements Map<K,V> Serializable{
    private static final long serialVersionUID = 1978198479659022715L;
    private final Map<K,V> m; // Backing Map
    final Object mutex; // Object on which to synchronize
    SynchronizedMap(Map<K,V> m) {
    this.m = Objects.requireNonNull(m);
    mutex = this;
    }
    SynchronizedMap(Map<K,V> m, Object mutex) {
    this.m = m;
    this.mutex = mutex;
    }
    public int size() {
    synchronized (mutex) {return m.size();}
    }
    public boolean isEmpty() {
    synchronized (mutex) {return m.isEmpty();}
    }
    public boolean containsKey(Object key) {
    synchronized (mutex) {return m.containsKey(key);}
    }
    public boolean containsValue(Object value) {
    synchronized (mutex) {return m.containsValue(value);}
    }
    public V get(Object key) {
    synchronized (mutex) {return m.get(key);}
    }
    public V put(K key, V value) {
    synchronized (mutex) {return m.put(key, value);}
    }
    public V remove(Object key) {
    synchronized (mutex) {return m.remove(key);}
    }
    // 省略其他方法
    }
    从源码中可以看出,synchronizedMap()方法返回一个SynchronizedMap类的对象,而在SynchronizedMap类中使用了synchronized同步关键字来保证对Map的操作是线程安全的

    HashMap为什么是非线程安全?

    void addEntry(int hash,K key,V value,int bucketIndex){
      Entry<K,V> e = table[bucketIndex];
      table[bucketIndex] = new Entry<K,V>(hash,key,value,e);
      if(size++ >= threshold){
        resize(2*table.length);
      }
    
    }
    

    原因一:hashMap做put操作的时候调用addEntry方法,现在假如A线程和B线程同时对同一个数据位置调用该方法,两个线程会同时得到头节点,A写入头节点以后B也写入新的头节点,那B的写入操作造成A的写入操作丢失。

    addEntry中当加入新的键值对后键值对总数超过门限值的时候会调用一个resize操作,代码如下:
    void resize(int newCapacity){
    Entry[] oldTable = table;
    int oldCapacity = oldTable.length;
    if(oldCapacity == MAXIMUM_CAPACITY){
    threshold = Integer.MAX_VALUE;
    return;
    }
    Entry[] newTable = new Entry[newCapacity];
    transfer(newTable);
    table = newTable;
    threshold = (int)(newCapacity * loadFactor);
    这个操作会生成一个新的容量的数组,会对原数组的所有键值对重新进行计算和写入新的数组,之后指向新的数组。
    原因二:当多个线程同时检测需要进行resize()操作,各自生成新的数组并rehash后赋给该map底层的数组table,结果最后只有一个线程生成的新数组被赋给table变量,其他线程的均丢失。
    Map testmap = Collection.synchronizedMap(new HashMap())

    equals()方法和hashCode()方法

    java.lang.Object类中有两个非常重要的方法
    public boolean equals(Object obj)
    public int hashCode()
    Object是类继承结构的基础,是所有类的父类

    equals()

    public boolean equals(Object obj){
        return (this == obj)
    }
    

    是对两个对象的地址值进行比较。但String、Math、Integer、Double等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法
    如在String类中如下:
    public boolean equals(Object anObject){
    if(this == anObject){
    return true;
    }
    if(anObject instanceof String){
    String anotherString = (String)anObject;
    int n = count;
    if(n == anotherString.count){
    char v1[] = value;
    char v2[] = anotherString.value;
    int i = offset;
    int j = anotherString.offset;
    while(n-- != 0)//对每一位置逐一比较
    {
    if(v1[i++] != v2[j++]
    return false;
    }
    }
    return true;
    }
    }
    return false;
    }
    类推Math、Integer、Double等类都重写了equals()方法,还有基本类型也是进行内容的比较

    注意:当equals方法被override时,hashCode()也要被override。按照一般hashCode()方法的实现来说,相等的对象,它们的hash code一定相等

    hashCode

    1. 在一个java应用的执行期间,如果一个对象提供给equals做比较的信息没有被修改的话,该对象多次调用hashCode方法,始终返回同一个integer。
    2. 如果两个对象根据equals(Object)方法是相等的,那调用二者各自的hashCode()方法必须产生同一个integer结果。
      在Object类中,hashCode定义如下:
      public native int hashCode();
      说明是本地方法,实现跟本地机器有关,如String、Integer、Double等这些类都覆盖了hashCode方法,String中定义的hashCode()方法如下:
      public int hashCode(){
      int h = hash;
      if(h == 0){
      int off = offset;
      char val[] = value;
      int len = count;
      for(int i=0;i<len;i++){
      h = 31*h+val[off++];
      }
      hash = h;
      }
      return h;
      }

    ArrayList 和 linkedList

    1. ArrayList实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
    2. 对于随机访问,ArrayList优于LinkedList
    3. 对于新增和删除操作,LinkedList优于ArrayList

    ArrayList

    ArrayList,在声明对象时并不需要指定它的长度,对象的大小是按照其中存储的数据来动态扩充和收缩的。

    数组扩容是对ArrayList效率影响较大的一个元素。
    每当执行Add、AddRange、insert、insertRange等添加元素的方法,都会检查内部数组的容量是否够用。若不够,以当前容量的两倍来重新构建数组,将旧元素COPY到数组中,然后丢弃旧数组

    特定类型(Object除外)的数组的性能优于ArrayList的性能,因为ArrayList的元素属于Object类型,所以在存储或检索值类型时通常发生装箱和取消装箱的操作。

    map、list、set

    list 有序可重复
    set 无序不可重复
    map 按键值对存储,无放入顺序

    List接口有三个实现类:LinkedList、ArrayList、Vector
    Set接口有两个实现类:HashSet(底层由HashMap实现),LinkedHashSet
    Map接口有三个实现类:HashMap、HashTable、LinkedHashMap
    HashMap allows one null key and any number of null values.,而Hashtable则不行
    HashTable是synchronized的,是线程安全的,而HashMap不是

    相关文章

      网友评论

          本文标题:java随笔

          本文链接:https://www.haomeiwen.com/subject/yijyfxtx.html