java基础知识点及跳转链接

学习链接
https://www.zhihu.com/question/354597734/answer/885933007
面试问题链接
https://zhuanlan.zhihu.com/p/86536581

问题:
1、hashcode()/equals()
hashcode由对象地址转化而来
equals方法默认比较对象地址,使用==运算符 因此重写equals必须重写hashcode
因为规定两个对象的equals相等,则hashcode一定相等
关于==/equals/hashcode/toString


2、
transient 将不需要序列化的属性设为transient,生命周期仅存于调用者的内存,不会序列化保存到磁盘或者网络传输
被static修饰的变量在序列化时其变量值不会被保存
volatile 保证并发时该字段的可见性,且该字段在指令重排时不做操作。


3、关于Object的clone以及深拷贝/浅拷贝
浅拷贝:浅拷贝是指在拷贝时只拷贝该对象的基本数据类型,若对象中有额外的引用数据类型,其只会拷贝该引用的地址到该位置
深拷贝:在拷贝的时候不仅拷贝基本数据类型,同时会将引用数据类型的数据在内存中重新开辟空间复制一份后,将新申请的地址赋给新的拷贝对象


4、wait和notify方法


5、finalize()方法

是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法
当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。


6、基本类型和包装类型的区别,涉及自动装箱和拆箱原理
过程
(-128–127) 直接调用相应包装类Integer.valueOf()
不在(-128–127)之内,直接new对象 Integer a=new Integer(200) Integer b=new Integer(200) a==b//false 注:只要实际值相同,则hashcode相等
在这里插入图片描述 在这里插入图片描述

自动拆箱:底层调用了相应的xxxValue() Integer a=100 int b=a.intValue();


7、关于List
list总结公众号
ArrayList/LinkedList优势、扩容、何时用

在这里插入图片描述


在这里插入图片描述
8、Collection集合
collection总结链接
常见容器:StringBuffered/数组
集合只能存储引用类型(Integer/Boolean等)
——collection
————List 有序可重复
——————ArrayList
——————LinkedList
——————Vector

List接口实现ListIterator接口
Iterator–next()/hasNext()/remove()
hasPrevious()/previous()/nextIndex()/previousIndex()/set(E)/add(E)

————Set 无序不可重复
——————hashSet
——————TreeSet
——————LinkedHashset

重点方法介绍
Iterator() Collection接口继承Iterable接口

List<String> list=new ArrayList<String>();
		list.add("hello1");
		list.add("hello2");
		list.add("hello3");
		
		Iterator it=list.iterator();
		while(it.hasNext()) {
			//it.next() 返回Object
			String s=(String)it.next();
			it.remove();
			System.out.println(s);
		}

9、关于Set


10、关于Map
Map知识点参考链接
也称为映射;将键映射到值的对象,一个映射不能包含重复的键,每个键最多映射到一个值
map集合存储元素是成对出现的,map的键是唯一的,值可重复
map集合的数据结构针对键有效,跟值无关

不在意元素的顺序,能够快速的查找元素的数据–散列表
java中散列表使用链表数组实现,每个列表称为桶
散列表为每个对象计算出一个整数,称为散列码,根据这些计算出来的整数(散列码)保存在对应的位置上
在这里插入图片描述
若hashcode散列码相同,存储在同一位置,形成散列冲突,则:
若该对象存在于桶上,不添加,若不存在添加到桶上
在JDK1.8中,桶满会从链表变成平衡二叉树
如果散列表太满,是需要对散列表再散列,创建一个桶数更多的散列表,并将原有的元素插入到新表中,丢弃原来的表
装填因子(load factor)决定了何时对散列表再散列
装填因子默认为0.75,如果表中超过了75%的位置已经填入了元素,那么这个表就会用双倍的桶数自动进行再散列
关于树的总结知识

		Map<Integer,Integer> map=new HashMap<Integer,Integer>();
		//添加
		Integer result1 =map.put(1, 1);
		Integer result2 =map.put(1, 2);
		map.put(2, 2);
		map.put(3, 3);
		map.put(4, 4);
		
		System.out.println(result2);//若键第一次存储,返回null,否则,返回被替代掉的值
		//删除
		Integer result3=map.remove(1);//根据键删除值,将值返回
		map.clear();//清空
		//判断功能
		boolean flag;
		flag=map.containsKey(3);//判断集合是否包含指定键
		flag=map.containsValue(3);//判断集合是否包含指定值
		flag=map.isEmpty();//判断是否为空
		//获取功能
		Integer result4=map.get(3);//根据键获取值
		Set<Integer> setKey=map.keySet();//获取集合中所有键的集合
		Collection<Integer> colletionValue=map.values();//获取集合中所有值的集合
		Set<Map.Entry<Integer, Integer>> set=map.entrySet();//键值对对象的集合  //需要补充使用方式
		//长度
		int c=map.size();

在这里插入图片描述
hashMap计算方式hashMap计算详解
在这里插入图片描述
11、final
可修饰类/方法/变量(成员变量和局部变量)
表示类不能被继承
继承该类的类不能修改该方法
对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。但是它指向的对象的内容是可变的。
注:类的private方法会隐式地被指定为final方法。


12、
快速失败:在并发环境下进行迭代操作,若其他线程对其进行了结构性修改,迭代器可以立马感知并立即抛出ConcurrentModificationException异常
13、hashmap与hashtable区别
hashmap 先检查是否扩容再插入 默认容量16 线程不安全 计算hash值首先要同时考虑插入对象hashcode的高位和低位,尽量避免仅考虑低位的冲突 允许键为null和多个值为null 扩容为2n
hashtable 先插入再检查是都扩容 默认容量 11 线程安全,使用synchronize hash值计算时直接取余 不允许键和值为null 扩容为2n+1


14、native
native方法是指存在于本地方法栈中的方法,其均为c/c++实现,为底层方法。同时,在程序运行到本地方法栈的代码时,其程序计数器【一般为正在运行的代码行的行数】值为0


15、永久代与元空间
jdk1.7及以前 永久代
jdk1.8及以后 元空间 元空间不在虚拟机中,而是使用本地内存


16、成员变量和局部变量
成员变量在方法外部,类内部定义的变量,存储在堆中的对象里面,由垃圾回收期负责回收
局部变量在方法或语句块内部定义的变量,必须初始化
存在于栈内存中,会随着方法的消失而消失
成员变量的内存与赋值过程


17、java加载类机制
java源文件被javac编译为class字节码文件
javac编译时不进行连接工作,而是在jvm运行时动态加载和动态连接
在这里插入图片描述
加载:类加载器将类的二进制字节流代表的类结构转化到运行时数据区的方法区,最后在jvm堆中生成表示这个类的java.lang.Class实例
在这里插入图片描述
验证verification:与loading是交叉进行的,验证二进制字节流代表的字节码文件是否合格
准备preparation 在方法区中给类的类变量(static修饰)分类内存
public static int value=123
在准备阶段,将value值设为0而不是123,当类初始化的时候才将value设为123
解析resolution 将class常量池内的符号引用替换为直接引用的过程
初始化initialization

主动引用:
new 对象时
读取或设置类的静态字段(除了 被final,已在编译期把结果放入常量池的 静态字段)或调用类的静态方法时;
用java.lang.reflect包的方法对类进行反射调用没初始化过的类时 初始化一个类时发现其父类没初始化,则要先初始化其父类
含main方法的那个类,jvm启动时,需要指定一个执行主类,jvm先初始化这个类
其他对类的引用 称为被动引用,加载类时不会进行初始化动作

//父类Animal
class Animal {  
/*8、执行初始化*/  
    private int i = 9;  
    protected int j;  
 
/*7、调用构造方法,创建默认属性和方法,完成后发现自己没有父类*/  
    public Animal() {  
/*9、执行构造方法剩下的内容,结束后回到子类构造函数中*/  
        System.out.println("i = " + i + ", j = " + j);  
        j = 39;  
     }  
 
/*2、初始化根基类的静态对象和静态方法*/  
    private static int x1 = print("static Animal.x1 initialized");  
    static int print(String s) {  
        System.out.println(s);  
        return 47;  
    }  
}  
 
//子类 Dog
public class Dog extends Animal {  
/*10、初始化默认的属性和方法*/ 
    private int k = print("Dog.k initialized");  
 
/*6、开始创建对象,即分配存储空间->创建默认的属性和方法。 
     * 遇到隐式或者显式写出的super()跳转到父类Animal的构造函数。
     * super()要写在构造函数第一行 */  
    public Dog() { 
/*11、初始化结束执行剩下的语句*/
        System.out.println("k = " + k);  
        System.out.println("j = " + j);  
    }  
 
/*3、初始化子类的静态对象静态方法,当然mian函数也是静态方法*/  
    private static int x2 = print("static Dog.x2 initialized");
 
/*1、要执行静态main,首先要加载Dog.class文件,加载过程中发现有父类Animal, 
    *所以也要加载Animal.class文件,直至找到根基类,这里就是Animal*/       
    public static void main(String[] args) {  
 
/*4、前面步骤完成后执行main方法,输出语句*/ 
        System.out.println("Dog constructor"); 
/*5、遇到new Dog(),调用Dog对象的构造函数*/  
        Dog dog = new Dog();   
/*12、运行main函数余下的部分程序*/            
        System.out.println("Main Left"); 
    }  
}

18、java编译过程
编译后的字节码文件格式主要分两部分:常量池和方法字节码
常量池:代码出现过的字面量(文本字符串、八种基本类型的值、被声明为final的常量等)以及符号引用(类和方法的全限定名、字段的名称和描述符、方法的名称和描述符)
方法字节码中放的是各个方法的字节码(依赖操作数栈和局部变量表,由JVM解释执行)

字符串常量池

jdk1.6之前 放在方法区,以后放在堆中
实现细节:HotSpot实现的string pool功能是一个StringTable类,为hash表,默认1009长度

class常量池

每一个Java类被编译后,就会形成一份class文件;class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References);每个class文件都有一个class常量池
字面量包括:
1.文本字符串 2.八种基本类型的值 3.被声明为final的常量等;
符号引用包括:
1.类和方法的全限定名 2.字段的名称和描述符 3.方法的名称和描述符。

运行时常量池

运行时常量池存在于内存中,也就是class常量池被加载到内存之后的版本,不同之处是:它的字面量可以动态的添加(String#intern()),符号引用可以被解析为直接引用
JVM在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。而当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,由此可知,运行时常量池也是每个类都有一个。在解析阶段,会把符号引用替换为直接引用,解析的过程会去查询字符串常量池,也就是我们上面所说的StringTable,以保证运行时常量池所引用的字符串与字符串常量池中是一致的。


19、java并行与并发
并行:多个事件在同一时刻发生 多核处理器处理不同任务,物理上的同时发生
并发:多个事件在同一时间间隔发生 逻辑上的同时发生
可能一个程序需要另一个程序的计算结果,也可能多个程序竞争某一资源,且程序是走走停停的


20、java中各种数据类型在内存中的位置
java中各数据类型在内存中的位置
(1)在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;
(2)堆内存用来存放由new创建的对象和数组以及对象的实例变量。在函数(代码块)中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间;在堆中分配的内存由java虚拟机的自动垃圾回收器来管理
a)基本数据类型:int a=3; a指向int类型的引用,指向3这个字面量,字面量存在于栈中,且字面量可以共享,如int b=3;
b)对象
c)创建多个不同的对象实例
d)包装类
e)String
f)数组
g)静态变量


21、StringBuffer的使用
StringBuilder不是线程安全,速度快
StringBuffer线程安全,速度慢

StringBuffer s=new StringBuffer();
		s.append("abc");
		s.append("def");
		String s1=s.toString();

22、静态分配和动态分配


23、strictfp
一旦使用了关键字strictfp来声明某个类、接口或者方法时,那么在这个关键字所声明的范围内所有浮点运算都是精确的,符合IEEE-754规范的。例如一个类被声明为strictfp,那么该类中所有的方法都是strictfp的。


24、switch使用byte/short/char/int或者对其的包装类/enum/String


25、子类无法覆盖父类的static方法和private方法
子类函数的访问修饰符要>=父类的访问修饰符


26、接口和抽象类


27、静态内部类与非静态内部类


28重写和重载
重写发生在子类不想完全继承父类的方法子类有自己想要定义的行为,在参数、返回值、方法名均相同的情况下对方法进行重写(override),但是重写该方法要求满足:访问权限应大于等于父类方法的访问权限

注:
override时返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类
被static和final修饰的方法不能被重写
构造方法不能被重写 调用父类中被重写的方法使用super

重载发生在一个类中,表现形式为改变方法的参数顺序、参数类型、参数个数。是类编译时多态性的体现。重载的方法可以有返回值也可以没有返回值,该条件不作为判断重载的依据


29、多态
多态是同一个行为具有多个不同表现形式或形态的能力
实现方式:重写、继承、抽象类
必要条件:继承、重写、父类引用指向子类对象(向上转型)
重写是父类与子类多态性的表现
重载是同一个类中的多态性表现


1、javabean是什么
2、为什么需要使用反射动态构建对象?
3、关于hashcode、equals、toString、Comparable、clone
原文地址:https://blog.csdn.net/qq_21688757/article/details/53039719
引用数据类型:String/引用变量
基本数据类型:byte,short, int, long, float, double, char, boolean;【直接存储在内存中的内存栈上】
==和equals()的区别
前者的==比较的是栈内存中存放的引用堆内存中对象的引用地址
equals比较两个值是否相等,而不是比地址
注:equals不能用于基本数据类型,只能用于类变量。对于基本数据类型要用类包装

		Integer a=129;
		Integer b=129;
		System.out.println(a.equals(b));//true 内容相同
		System.out.println(a==b);//false 引用不同

注意:Integer类型在0-127之间时采用自动装箱,比较值相同,但当大于阈值时会自己封装,引用的时候地址不同
“==”比equals方法的运行速度快,因为“==”只是比较引用

在这里插入图片描述

常量池的基本概念:Java是一种动态连接的语言,常量池的作用非常重要,常量池中除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值还,还包含一些以文本形式出现的符号引用。
但是在new出一个对象时,即使两个对象的属性值均相同,但是由于对象在堆内存里面存储在不同的空间里面,所以对象永远不会相等

Cat c1=new Cat(1,1,1);
Cat c2=new Cat(1,1,1);
c1==c2?//false
c1.equals(c2) //false

当new一个对象时,将在内存中加载一份它自己的内存,而不是共用。
https://blog.csdn.net/qq_21688757/article/details/53067814?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.nonecase
关于HashCode
java的collection有两类:
List:有序可重复
Set:无序不可重复
要想保证元素不重复,则使用equals方法,但是若一直使用该方法效率过低,因此采用哈希表的原理。

当Set接收一个元素时根据该对象的内存地址算出hashCode,看它属于哪一个区间,再这个区间里调用equeals方法。【特别注意】这里需要注意的是:当俩个对象的hashCode值相同的时候,Hashset会将对象保存在同一个位置,但是他们equals返回false,所以实际上这个位置采用链式结构来保存多个对象。
在这里插入图片描述
对于eqauls方法和hashCode方法是这样规定的:
1 如果两个对象相同,那么它们的hashCode值一定要相同。也告诉我们重写equals方法,一定要重写hashCode方法,也就是说hashCode值要和类中的成员变量挂上钩,对象相同–>成员变量相同—->hashCode值一定相同。
2 如果两个对象的hashCode相同,它们并不一定相同,这里的对象相同指的是用eqauls方法比较。

HashSet<RectObject> set = new HashSet<RectObject>();  
        RectObject r1 = new RectObject(3,3);  
        RectObject r2 = new RectObject(5,5);  
        RectObject r3 = new RectObject(3,3);  
        set.add(r1);  
        set.add(r2);  
        set.add(r3);  
        set.add(r1);  
        System.out.println("size:"+set.size());  

重写hashcode和equals方法:
结果:size=2
hashcode值 r1=r3
equals方法:r1=r3
只重写equals方法:
结果:size=3
由于原hashcode值是根据内存地址计算的,所以r1的hashcode值与r3的hashcode值不同,所以set中为r1、r2、r3
只重写hashcode方法:
结果:size=3
r1的hashcode值!=r2
r1的hashcode值==r3==r4
r1的equals!=r2!=r3!=r4

内存泄漏情况
package com.weijia.demo;
import java.util.HashSet;
public class Demo {
    public static void main(String[] args){
        HashSet<RectObject> set = new HashSet<RectObject>();
        RectObject r1 = new RectObject(3,3);
        RectObject r2 = new RectObject(5,5);
        RectObject r3 = new RectObject(3,3);
        set.add(r1);
        set.add(r2);
        set.add(r3);
        r3.y = 7;
        System.out.println("删除前的大小size:"+set.size());
        set.remove(r3);
        System.out.println("删除后的大小size:"+set.size());
    }
}

删除前后均为3
因为删除前,r3的属性值参与计算hashcode值中计算存储位置,但是由于改变了r3的属性值,在删除r3时会先计算r3的hashcode值,但是由于hashcode值的改变会导致找不到r3,删除不了引起内存泄漏。
关于toString

基本类型—>String类型
String.valueOf(boolean b) 将b转化为字符串 String valueOf(char[] data,int offset,int count)
将char中的data由data[offset]开始读取,读取count个元素转化为String String
str=Integer.toString(10);
String—>基本数据类型
int a=Integer.parseInt(String s);//返回int
parseXXX(String s)

public String toString()返回该对象的字符串表示
Object的toString方法返回一个字符串
类名(对象为该类的一个实例)+@+此对象哈希码的无符号十六进制表示组成
getClass().getName()+’@’+Integer.toHexString(hashCode())
java

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值