Java基础(一)
文章目录
1. JDK和JRE区别
-
JDK:Java Development Kit
-
JRE:Java Runtime Environment
2. Java原始数据类型(封装类)
- 字符型:byte(Byte)、char(Character)
- 布尔型:boolean(Boolean)
- 数字型
- 整数型:short(Short)、int(Integer)、long(Long)
- 浮点型:double(Double)、float(Float)
3. ==和equals区别
-
==
- 基本类型:比较值是否相同
- 引用类型:比较引用是否相同
-
equals
- 本质是==
- 很多类(如String、Integer等包装类)重写了equals方法,实现了值的比较,所以一般情况下我们使用的是已经重写过的equals方法,比较的是值是否相等。
//Integer public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; } //String 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; }
4. hashCode()的作用
- 用来在散列存储结构中确定对象的存储地址(HashMap、HashTable等)
- 如果两个对象相同(equals()为true),那么他们的hashCode一定要相同
- 两个对象的hashCode相同,不一定表示两个对象相同(equals()不一定为true),只能够说明这两个对象在一个散列存储结构中。。
- 重写equals()方法的同时尽量重写hashCode()方法
扩展1:java中hash寻域过程
哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。这样一来,当集合要添加新的元素时,先调用这个元素的HashCode方法,就一下子能定位到它应该放置的物理位置上。
(1)如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;
(2)如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了;
(3)不相同的话,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将所有产生相同HashCode的对象放到这个单链表上去,串在一起。这样一来实际调用equals方法的次数就大大降低了。
所以hashCode在上面扮演的角色为寻域(寻找某个对象在集合中区域位置)
参考:https://blog.csdn.net/a745233700/article/details/83186808
扩展2:处理hash冲突方法
- 开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)
- 再哈希法
- 链地址法(Java.HashMap)
- 建立公共溢出区
参考:https://blog.csdn.net/porsche_gt3rs/article/details/79445707
5. final 作用
- final 修饰的变量叫做常量,定义常量必须在声明时初始化,且初始化后的值不能被修改
- final修饰的类叫做最终类,不能被继承。
- 将类声明为final,意味着此类在继承树中是一个叶子类,被认为是完美的,以后都不会进行修改或扩展;
- final类因为无法被继承,那么其成员方法自然也就成了final型的,没有机会被覆盖,加不加final都没有意义。
- final修饰的方法不能被重写
- 将方法声明为final,说明此方法已完美,不再需要进行扩展,且不允许任何从继承此类的类来覆写该方法,但是仍然可以继承该方法,可以直接使用。
- inline机制:在调用final方法时,会直接将方法主体插入到调用处,而不是进行例行的方法调用,这样可能会使程序效率有所提高,但是如果方法主体非常庞大或多处调用此方法时,你的调用主体代码就会迅速膨胀,可能反而影响到效率,慎用final进行方法定义。
参考:https://zhidao.baidu.com/question/539549553.html
6. String、StringBuffer、StringBuilder区别
- String
- String声明的是不可变对象,每次操作都会生成新的String对象,然后指针指向新对象
- StringBuffer
- 在原有字符串对象基础上操作
- 线程安全,多线程使用
- StringBulider
- 在原有字符串对象基础上操作
- 非线程安全,单线程使用
- 性能高于StringBuffer
7. String str="i"与 String str=new String(“i”)的区别
内存分配方式不一样:
1. String str =“i”,JVM将其分配到常量池
2. String str = new String(“i”),分配到堆内存
7.1 扩展:JVM内存区域:
- 寄存器:JVM内部虚拟寄存器,存取速度非常快,程序不可控制。
- 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中。
- 堆:存放new出来的对象,注意创建出来的对象只包含各自的成员变量,不包括成员方法。
- 常量池:存放常量,如基本类型的包装类(Integer、Short)和String,注意常量池位于堆中。
- 代码段:用来存放从硬盘上读取的源程序代码。
- 数据段:用来存放static修饰的静态成员。
参考:https://blog.csdn.net/jian_sheng_tan/article/details/78323327
8. 反转字符串
StringBuilder、StringBuffer提供reverse()方法。
StringBuffer strBuffer = new StringBuffer();
strBuffer.append("abc");
System.out.println(strBuffer); //abc
System.out.println(strBuffer.reverse());//cba
StringBuilder strBuilder = new StringBuilder();
strBuilder.append("123");
System.out.println(strBuilder); //123
System.out.println(strBuilder.reverse()); //321