java 基础

基础

1, static 关键字 表明在没有所属类的实例变量的情况下被访问。

static方法就是没有this的方法。在static方法内部不能调用非静态方法。

静态变量被所有的对象所共享,在内存中只有一个副本,它只在类初次加载时会被初始

不能被覆盖。

2, 覆盖方法是基于运行时动态绑定的,static 是编译时静态绑定的。

3, java 运行时环境(jre),包括java虚拟机,java核心类库和支持文件

4, java 开发工具(jdk) , 完整的java软件包, 包含jre, 编译器, 其他工具javaDoc, 调试器等



序列化

序列化就是把对象转化为0和1二进制编码,有两个作用1.用于网络传输。2.可以存储到硬盘中,用来保存。

使用场景:所有可在网络上传输的对象都必须是可序列化的,比如RMI(remote method invoke,即远程方法调用),传入的参数或返回的对象都是可序列化的,否则会出错;

所有需要保存到磁盘的java对象都必须是可序列化的。

对象相等

equals

Object类中的equals方法和“==”是一样的,没有区别,即俩个对象的比较是比较他们的栈内存中存储的内存地址。


当需要判断对象是否相等时(如对象作map的key,唯一),需重写equals

如果不重写equals()方法,相同的内容不同引用的对象会被当做不同的对象被使用


重写equals方法的要求:

1、自反性:对于任何非空引用x,x.equals(x)应该返回true。

2、对称性:对于任何引用x和y,如果x.equals(y)返回true,那么y.equals(x)也应该返回true。

3、传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true。

4、一致性:如果x和y引用的对象没有发生变化,那么反复调用x.equals(y)应该返回同样的结果。

5、非空性:对于任意非空引用x,x.equals(null)应该返回false。


注意:1、重写equals必须重写hashCode方法  因为是先比较两个对象的hash值是否相等在判断值         

2、equals() 和 hashCode() 的定义必须兼容 如果 x.equals(y) 则x , y 的hashCode必须相等,

3、x , y 的 hashCode相等,x , y 不一定相等


hashCode

什么是哈希码?就是一套算法算出来的一个值,且这个值对于这个对象相对唯一。在Java应用程序执行期间,在对同一对象(未修改)多次调用 hashCode 方法时,必须一致地返回相同的整数。


1如果散列表中存在和散列原始输入K相等的记录,那么K必定在f(K)的存储位置上

2不同关键字经过散列算法变换后可能得到同一个散列地址,这种现象称为碰撞

3如果两个Hash值不同(前提是同一Hash算法),那么这两个Hash值对应的原始输入必定不同

可以理解为K多对一 Hash,因为f(K)不会有俩个计算结果hash, 而有可能f(K1)=f(K2)=Hash


hashCode的作用,用来查找 对象在内存中的位置。 如 把K的hashCode % 9,算出的结果则为内存的结果,有数据了则取决于算法去加1或者链表。

查找的时候,对比对象是否相同时候,则先对比hashCode,如果不同则不同,相同则在对比equals。


String就是一个对象,本质是个char[] ,自己重写了equals和hashCode, 遍历char数组中的每个字符来实现equals和hashCode。

public int hashCode() {

        int h = hash;

        if (h == 0 && value.length > 0) {

            char val[] = value;

            for (int i = 0; i < value.length; i++) {

                h = 31 * h + val[i];

            }

            hash = h;

        }

        return h;

}

使用String的 char 数组的数字每次乘以 31 再叠加最后返回,因此,每个不同的字符串,返回的 hashCode 肯定不一样。


在名著《Effective Java》第 42 页就有对 hashCode 为什么采用 31 做了说明:

之所以使用31, 是因为他是一个奇素数。如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算(低位补0)。使用素数的好处并不很明显,但是习惯上使用素数来计算散列结果。 31 有个很好的性能,即用移位和减法来代替乘法,可以得到更好的性能: 31 * i == (i << 5) - i, 现代的 VM 可以自动完成这种优化。这个公式可以很简单的推导出来。

集合

Collection

├List (有序集合,允许相同元素和null)

│├LinkedList (非同步,允许相同元素和null,遍历效率低插入和删除效率高)

│├ArrayList (非同步,允许相同元素和null,实现了动态大小的数组,遍历效率高,用的多)

│└Vector(同步,允许相同元素和null,效率低)

│ └Stack(继承自Vector,实现一个后进先出的堆栈)

└Set (无序集合,不允许相同元素,最多有一个null元素)

     |-HashSet(无序集合,不允许相同元素,最多有一个null元素)


Map (没有实现collection接口,key不能重复,value可以重复,一个key映射一个value)

├Hashtable (实现Map接口,同步,不允许null作为key和value,用自定义的类当作key的话要复写hashCode和eques方法,)

├HashMap (实现Map接口,非同步,允许null作为key和value,用的多)

└WeakHashMap(实现Map接口)



泛型的定义:在程序中我们将一个对象放入集合中,但是集合不会记住对象的类型,当我们在次使用对象的时候,对象变为Object类型,而程序中还是原来的类型,我们必须要自己转换其类型,为了解决这个问题,则提出泛型。


Java中数组是对象,父类是Object,每个数组都实现了接口Cloneable and java.io.Serializable

有自己的类名,如int[]的类名是 [I

Arrays

Arrays类位于 java.util 包中,主要包含了操纵数组的各种方法, 有搜索,排序,填充,复制等。


Arrays.asList(T… data)

注意:该方法返回的是Arrays内部静态类ArrayList,而不是我们平常使用的ArrayList,,该静态类ArrayList没有覆盖父类的add, remove等方法,如果直接调用,会报异常。


hashMap

Key常用String ,string已经重写了hashCode


HashMap中定位到桶的位置 是根据Key的hash值与数组的长度取模来计算的。getNode() 方法中

p = tab[i = (n - 1) & hash] 


可以理解为,将hash的 bit 位截取到 (n - 1) 的 bit 位长度。并找到该字节对映的 node 数组坐标中的值。所以数组的长度都要为2^n。



hash方法:return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

可以看成是hashCode高位 和 地位 的异或计算得到的hash值。

可以真正的动一位则动全身。不论高位还是低位,只要有一位不同,计算存储位置相同的概率就会大幅度降低(但是还是有的)。


你可能感兴趣的:(java 基础)