概述
目录
1.面向对象的三大特征
2.重写跟重载
3.访问修饰符(从最弱到最严格)
4.基本数据类型
5.==和equals区别
7.String值不可变,不可被继承的本质
8.位运算的选择
9.&&和||
10.反射机制
11.深拷贝和浅拷贝
12.并行和并发
13.类的初始化
14.静态变量和成员变量
15.抽象类和接口
16.error和exception
17.list,set,map
18.ArrayList和LinkedList
19.HashMap
20.线程
21.synchronized和Lock区别
22.类加载器(从上到下,双亲委派机制从下到上)
23:类加载过程
24:双亲委派机制
25:垃圾回收机制
1.面向对象的三大特征
继承:子类继承父类的特征和行为,让子类对象具有父类的方法和行为
封装:隐藏对象的属性和实现细节,对数据的访问只能通过外公开的接口,一种对内部数据的保护行为
多态:对于同一个行为,不同的子类对象具有不同的表现形式
存在条件:1.继承
2.重写
3.父类引用指向子类对象
2.重写跟重载
重写:子类继承父类,他具有父类的所有方法和行为,但是他可以对父类的方法进行修改,以增加功能。
规则:1.子类的参数列表,返回类型必须跟父类保持一致,否则就是重载
2.被子类的重写方法不能拥有比父类更严格的访问权限,即如果父类的访问修饰符是private,则子类不能对其进行重写操作
3.重写的方法不能抛出新的异常
如果在子类中想要调用父类被重写的方法,可以使用super关键字。
重载:在一个类中,多个方法的方法名相同,但是参数列表不相同
规则:1.重载的参数列表必须不同,其他的都不能作为重载的判断条件
2.构造器可以被重载,但是不能被重写
3.访问修饰符(从最弱到最严格)
4.基本数据类型
1.8种基本数据类型:数据直接存储在栈上
byte: 8位 -128 —— 127
short:16位 -2^15 —— 2^15-1
int:32位 -2^31 —— 2^31-1
long:64位 -2^63 —— 2^63-1
float:128位 -2^127 —— 2^127-1
double:256位 -2^255 —— 2^255-1
boolean:只有true和false 默认值false
char:单一字符
2.引用数据类型:除去8中数据类型,其他都是引用数据类型数据,存储在堆上,栈上只存储引用地址,所以String肯定不是基本数据类型
tips:1.当基本数据类型进行计算时,小于int类型的计算会先将数据类型转为int然后进行计算
2.经典的问题1
short s1 = 1; s1 = s1 + 1;
short s1 = 1; s1 += 1;
上面因为类型不一致所有会报错,下面再运算前先进行了类型转换,然后再进行计算,所有会出正常的记过
3.经典的问题2
Integer a = 128, b = 128, c = 127, d = 127;
System.out.println(a == b);
System.out.println(c == d);
上面的返回false,下面的返回true。Integer 中的 IntegerCache 的默认范围导致的结果(-128-127),导致a,b是俩个不同的对象,而==对于包装类型时比较的是俩者是否是相同的对象,所以返回false。当然,IntegerCache 的默认范围是可以修改的,所以结果只针对默认情况
5.==和equals区别
==:对于基本数据类型,比较的是俩者的值是否相等,数据类型无关紧要;对于引用数据类型,比较的是俩个对象的地址是否相等,所以new出来的俩个对象必定不相等。
equals:比较俩个对象的值是否相等
String:值不可变
StringBuilder:值可以被修改,使用 synchronized 来保证线程安全,单线程大数据建议使用
StringBuffer:StringBuffer 的非线程安全版本,没有使用 synchronized,具有更高的性能,多线程大数据建议使用
tips:在进行频繁的字符串拼接时,建议使用StringBuilder类或者StringBuffer,不使用性能较低的String
7.String值不可变,不可被继承的本质
String是被final修饰的,final的规定是,在程序编写时,希望一个方法的行为在继承期间保持不变,而且不可被覆盖或者该写,就使用final方法去修饰。而且String作为java中使用最多的类型,该操作也很大程度上保证了程序的安全性
8.位运算的选择
通常情况下,位运算比普通的运算方法要快速,但是随着发展,很多编译器其实也就自己可以做一些优化,一昧的使用位运算反而可能得不偿失,不仅没有加速运算速度,也使得程序不是很美观
9.&&和||
&& :且
||:或
10.反射机制
反射是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能称为反射机制
11.深拷贝和浅拷贝
深拷贝:把复制的对象所引用的对象都复制了一遍
浅拷贝:只复制要复制的对象
区别:对于基本数据类型来说,深拷贝和浅拷贝完全没有区别;对于引用数据类型来说,深拷贝将对象和其引用对象都复制了一遍,而浅拷贝值复制了对象,那么我们对对象进行修改时,如果引起了原对象的引用对象的引用地址变动,那么浅拷贝变动的是原引用对象的地址变动,而深拷贝变动的是新的引用对象的引用地址变动(因为浅拷贝没有复制引用对象,所以只有原引用对象)
12.并行和并发
简单来说:当你在做一件事情时,另外一件事情也来了,你停止手中的事情去做另外一件事情,当另外一件事情结束时再回来做第一件事情,这叫做并发,而且同时做俩件事情,这叫做并行
13.类的初始化
父类静态变量(静态代码块)->子类静态变量(静态代码块)->父类非静态变量(非静态代码块)->父类构造器 ->子类非静态变量(非静态代码块)->子类构造器
14.静态变量和成员变量
静态变量:存在于方法区中,随着类加载而存在,类消失而消失,可以被对象和类调用
成员变量:存在于堆内存中,随着对象创建而存在,对象回收而释放,只能被对象调用
15.抽象类和接口
抽象类:只能单继承,可以有构造方法,可以有成员变量,可以有抽象方法
接口:可以多实现,不可以有构造方法,只能有静态变量,可以有抽象方法
16.error和exception
error是程序无法处理的或者不必处理的问题,exception是程序可以处理的问题
17.list,set,map
list:存储一组有序不唯一的的对象
set:存储一组唯一的对象
map:以键对值的方式(key-value)存储一组对象
18.ArrayList和LinkedList
ArrayList:底层基于动态数组实现,因此对于查询方法有很大的优势,根据index直接定位到该位置然后进行查询(内存的连续性),虽然线程不安全,但是由于经常做的是查询的方法,所以无关紧要,毕竟不存在完美的集合,如果非要追求安全可以使用Vector,Vector方法是在ArrayList方法基础上,增加一个synchronized 关键字。初始化长度为10,第一次扩容时会将长度变为1.5倍
LinkedList:底层基于链表实现,故而查询的时候无法通过index进行直接定位,而是需要从节头开始往后遍历,效率过低。在插入时,如果使用随机插入,ArrayList需要通过System.arraycopy 去移动节点后面的节点,从而效率较低,而使用顺序插入时,因为不需要移动借点后面的节点,使用插入效率反而高于LinkedList
19.HashMap
jdk1.8之后采用“数据+链表+红黑树”,1.7使用“数组+链表”
存取原理:即当你插入一个新的key-value值时,会先对key值进行hash运算(key.hashcode()),如果返回值相同,那么他们的存储位置相同的。此时使用equals方法去比较Entry的key值,如果返回值为true,则用新的value值去覆盖旧的,如果返回值我false,则将其Entry和原来的Entry形成链结构并插入头部。(头插法)
头插法:讲新的元素插入数组成为头部,旧的元素以新元素为头,形成链表
尾插法:以旧的元素为头部形成链表,当链表长度大于7的时候形成红黑树(根据泊松分布,大于8的时候红黑树的优势开始展示,所以转换成红黑树)
为什么使用尾插法:因为使用头插法,在多次hash冲突后,很容易引起环形链表
扩容机制:当容量超过负载因子时,进行扩容
初始长度:16(1<<4的位运算,原因是2的幂等便于计算,位运算效率高)
负载因子:0.75f(默认)
扩容:创建一个新的entry空数组,长度为原数组2倍,然后进行Rehash操作
Rehash:遍历原Entry数组,把所有的Entry重新Hash到新数组
ReHash原因: 因为hash的计算规则是 index = HashCode(Key) & (Length - 1),那么经过扩容后,length值发生了改变,计算出来的index值也发生了改变,所以必须要ReHash
hash计算规则:index = HashCode(Key) & (Length - 1)。因为hashmap中的indexfor方法,该方法传入的参数是hashcode和length俩个参数,然后直接返回HashCode(Key) & (Length - 1)的位运算结果值
安全性能:不安全,不能用在多线程中,建议使用ConcurrentHashMap
为什么重写equals方法必须先重写hashcode方法:对于hashmap来说,equals是比较俩个对象的内存地址,而hashmap是通过key的hashcode去查找index值,所以index值其实也形成了链表,所以为了保证相同的对象返回相同的的hash值,不同的对象返回不同的hash值,必须重写hashcode方法,然后才能使用equals方法
hashmap容许键对值都为null
LinkedHashMap:按照传值顺序进行存储的集合
20.线程
生命周期:新建,就绪,运行,阻塞,死亡
创建方法:1.继承 Thread 类
2.实现 Runnable 接口
3.实现 Callable 接口
sleep( )和wait( )的区别:
sleep( ):继承Thread 类,不会释放锁,可以在任何地方使用
wait( )类:继承Object类,会释放当前锁,只能在同步方法或者同步代码块中使用,需要notif( )方法唤醒
start( )方法和run( )方法的区别:
start( ):新启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到 CPU 时间片,就开始执行 run() 方法
run():普通的方法调用,在主线程中执行,不会新建一个线程来执行
21.synchronized和Lock区别
synchronized:Java关键字;线程会一直等待直到获得锁
Lock:一个接口;需要手动释放锁仿制死锁现象出现
22.类加载器(从上到下,双亲委派机制从下到上)
启动类加载器:(BootStrap)
扩展类加载器:(Extension)
应用程序类加载器:(System)
自定义加载器:
23:类加载过程
加载,验证,准备,解析,初始化
24:双亲委派机制
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,会抛出异常,让子类加载器去尝试加载
25:垃圾回收机制
在触发GC的时候,对死去的对象进行垃圾收理,然后使用对应的垃圾回收算法
如何判断对象是否死去:可达性分析算法(Java默认使用)和引用计数法
Young GC:新生代中Eden 区没有足够的空间,使用复制算法进行回收(老年代是用标记-清除算法和标记-整理算法)
Full GC:当准备要触发一次Young GC时,如果发现统计数据说之前Young GC的平均晋升大小比目前老年代剩余的空间大,则不会触发Young GC而是转为触发Full GC。(通常情况)
如果有永久代的话,在永久代需要分配空间但已经没有足够空间时,也要触发一次Full GC。
System.gc()默认也是触发Full GC。
heap dump带GC默认也是触发Full GC。
CMS GC时出现Concurrent Mode Failure会导致一次Full GC的产生。
最后
以上就是文艺荔枝为你收集整理的JAVA基础的全部内容,希望文章能够帮你解决JAVA基础所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复