赞
踩
数组初始化之后长度不可变,静态初始化即指定了同类型的值,动态初始化只是指定了数组长度,值是默认的。
数组是对象,存在于堆中,数组的引用变量存在于栈中,有时这个引用变量重新指向了别的数组,给人一种数组长度可变的假象。
数组使用之前必须初始化,数组的引用变量不必要,同时所有的局部变量必须初始化,原因是局部变量不会有默认的初始化值。
所有的局部变量,不管是基本类型还是引用类型的变量都是存在于方法栈中的;所有的引用变量所真正引用的对象,不管是数组还是
普通java对象都是存在于堆内存中的;堆内存中的对象不允许直接访问,必须通过引用变量访问。
内存分配&垃圾回收&内存泄漏
肆意创建对象导致内存减少,和垃圾回收负担加重,都会降低程序的运行性能。
变量分为成员变量和局部变量,成员变量分为实例变量和静态变量,局部变量分为形参、方法内的局部变量、代码块中的局部变量。
static只能修饰类里面的,不能修饰外部类、局部变量和局部内部类。
一个对象初始化之前肯定要先初始化对象所属的类,所以类变量先于实例变量初始化。
实例变量和非静态代码块的执行顺序是按代码排列顺序执行的,而他们俩都在构造器之前执行;静态的逻辑也是这样
A a = new B(); A为编译时类型,B为运行时类型,通过a引用实例变量时,值为声明类型的值,但当引用方法时,则是具体对象的值。简而言之就变量由声明类决定,方法由实际类型决定。
子类可以调用父类的变量和方法,反过来则不行,除非是重写情况下,另外相同名称的变量分属不同的类。
在jvm中,一个类只对应一个Class对象,每个类可以创建多个java对象
final修饰,变量变成常量,方法不能重写,类不能继承
没有static修饰的变量将会进行两轮赋值,第一轮是分配内存时的默认值,第二轮才是等号右边的值,而static修饰的变量只有一轮(bilibili-2.8那题结果就不一样了)。
宏变量的成立条件
a、该变量必须是final修饰的变量;
b、该变量必须在定义时就指定初始值(代码块或者构造器都不是);
c、该初始值必须是在编译时期就可以确定。
宏变量一旦形成,变量在编译时就会把变量换成具体的值,在运行时就不存在此变量了,只是存在一个值而已。
只要存在方法调用会影响值的情况,编译时就无法确定该值
final a=“ha1”;final b= “ha1”;final c=“ha”+String.valueOf(1),a==b结果是true,因为他们指向的都是缓冲池中的地址,
a==c的结果是false,因为他们指向不同的地址,即使他们的内容相同。
a=b+c,只有b和c是final修饰且值可确定才是宏变量,才会执行宏替换,a的值才会在编译时候确定
另外宏变量第二个条件指定初始值,必须是定义的同时指定,像在静态代码块中或者构造器中都不能成为宏变量。
内部类中的局部变量默认都有final修饰,不能赋值两次,否则会报编译错误。
将Map集合中所有的key集中起来就是Set集合
对hashset而言,采用hash算法的返回值决定元素的存储位置,hashmap的key也是如此,value只是key的附属物。另外其实hashset是通过hashmap实现的,你没听错,不是反过来,因为hashset就是hashmap的key集合,此时只要将hashmap的value设为PRESENT,一个静态的Object对象,即实现了HashSet,放入重复元素时,会失败,而不是覆盖。
HashSet中存放元素时,先判断hashcode()值是否相等,如果不相等,将元素放入集合,相等则继续比较equals方法,不相等同样放入集合,相同则表示重复了,不放入,因为List有序可重复,Set无序不可重复。
集合中存储的是对象的引用
ArrayList底层是数组,初始长度是10,LinkedLsit底层是双向链表,HashMap底层是数组、单向链表和红黑树,HashSet由HashMap实现,TreeMap底层是红黑树,且key要按一定顺序排列,TreeSet由TreeMap实现
Map.Entry就是一个key-value对
HashMap默认初始容量是16,实际容量总是2的指数倍,所以如果初始容量不是2的指数倍,则实际容量会比初始容量大,另外负载因子默认是0.75,阈值=容量*负载因子,当元素数>=阈值时,hashmap就会将总体容量扩充一倍,另外数组一个节点(桶)下对应的单向链表转为红黑树的树化阈值为8,当单向链表的长度>=树化阈值-1时,就会进行树化,及词条单向链表会变成红黑树。(简单说就是默认初始量是16,负载因子是0.75,阈值是12,当值>=12时,容量扩充一倍,数组每个节点对应一个桶,桶下面指向一个单向链表,此链表长度>=7时,就会变成红黑树,这个过程叫做树化,这是java8的新特性)
values()方法得到的value集合并不是List对象,而是$Values内部类对象,并且这个集合对象不能添加元素,只是用来遍历
Java中的transient关键字,transient是短暂的意思。对于transient 修饰的成员变量,在类的实例对象的序列化处理过程中会被忽略。 因此,transient变量不会贯穿对象的序列化和反序列化,生命周期仅存于调用者的内存中而不会写到磁盘里进行持久化。
ConcurrentHashMap线程安全,另外Collecions.synchronizedList方法可以将线程不安全的集合转成线程安全的集合
迭代器模式:Iterator是一个迭代器接口,每个集合实现类都要求有一个iterator()方法返回一个Iterator用于遍历集合,至于返回的实现类是怎样的,由集合自己实现
使用迭代器遍历元素时,每次获取一个元素之前都会检查当前合集的修改次数和遍历之前的修改次数是否相等,所以不可以对集合进行修改操作,否则会引发ConcurrentModificationException异常
使用迭代器遍历Map的三种方式
// 方法一:entryset public static void iteratorInstance1(Map map){ Set set = map.entrySet(); Iterator it = set.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); System.out.println(entry.getKey() + ";" + entry.getValue()); } } // 方法二:keyset public static void iteratorInstance2(Map map){ Set set = map.keySet(); Iterator it = set.iterator(); while (it.hasNext()) { String key = (String) it.next(); String value = (String) map.get(key); System.out.println(key + ";" + value); } } // 方法二:values public static void iteratorInstance3(Map map){ Collection collection = map.values(); Iterator it = collection.iterator(); while (it.hasNext()) { String value = (String) it.next(); System.out.println(value); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。