java随笔

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不是

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,295评论 18 399
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 6,939评论 0 62
  • 一、基本数据类型 注释 单行注释:// 区域注释:/* */ 文档注释:/** */ 数值 对于byte类型而言...
    龙猫小爷阅读 4,213评论 0 16
  • 面向对象主要针对面向过程。 面向过程的基本单元是函数。 什么是对象:EVERYTHING IS OBJECT(万物...
    sinpi阅读 1,023评论 0 4
  • 晚上接娃,通常是娃爹的活。我偶尔打个替班。 前几天,清明过后的那晚,雷电交加。我带着两把伞去接他。两把伞都蛮大的,...
    息语阅读 326评论 0 3