发表时间:2022-03-22来源:网络
1.正数的原码、反码、补码都一样
2.负数的反码 = 它的原码符号位不变,其他位取反(取反的意思:0 换成 1 、 1 换成 0 )
3.负数的补码 = 它的反码 +1
4.0的反码、补码都是0
在编译阶段根据静态类型可以确定重载方法
重写方法是在运行期间动态分派的
继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法。
Java中类只支持单继承,不支持多继承
Java中类支持多层继承
内部实现分为三个步骤:先比较引用是否相同(是否为同一对象),再判断类型是否一致(是否为同一类型),最后比较内容是否一致。
1.举例说明不重写会出现什么问题
public static void main(String[] args) { Student stu1 = new Student("张三", 20); Student stu2 = new Student("张三", 20); System.out.println(stu1.equals(stu2)); }不重写结果会返回false
2.说明出现问题的原因
equals方法默认继承的Object类,默认比较两个对象的内存地址
3.说明重写后解决了问题
重写后返回true
1.举例说明不重写会出现什么问题
public static void main(String[] args) { Student stu1 = new Student("张三", 20); Student stu2 = new Student("张三", 20); Map map = new HashMap(); map.put(stu1, 1); map.put(stu2, 2); System.out.println(map); }利用hashmap举例,上面已经重写了equals方法,理论上key相同的话,应该数据会被覆盖,但实际上打印了两个值,如下
2.说明出现问题的原因
因为在HashMap中,是根据key的hashcode值确定数组下标位置的,如果数组下标位置相同,先比较key的hashcode值,如果相同,再用equals方法对比,如果相等,则覆盖。
而如果不重写hashcode方法,默认比较的是物理地址,则stu1和stu2的hashcode值不同
3.说明重写后解决了问题
@Override public int hashCode() { return Objects.hash(name, stuId); }重写后两个对象的hashcode值相同,可以覆盖,结果打印一个值
1.说出结果
创建 1 个或者 2 个对象
2.解释结果
new String 会先去常量池中判断有没有此字符串,如果有则只在堆上创建一个字符串并且指向常量池中的字符串,如果常量池中没有此字符串,则会创建 2 个对象,先在常量池中新建此字符串,然后把此引用返回给堆上的对象
1.解释概念
值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,在函数内对参数进行修改,不会影响到实际参数。
引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数内,在函数内对参数所进行的修改,将影响到实际参数。
2.java参数传递特点
如果是基础类型,那么在方法传递的时候复制的是(栈中)基础类型的引用和值,如果是引用类型复制的是(栈中)引用地址。
3.结论
在Java中本质上只有值传递,也就说Java的传参只会传递它的副本,并不会传递参数本身
详解
1.总体说明static关键字的应用范围
static 关键字可用于变量、方法、代码块和内部类,表示某个特定的成员只属于某个类本身,而不是该类的某个对象。
2.分条说明用法
2.1静态变量
1)由于静态变量属于一个类,所以不要通过对象引用来访问,而应该直接通过类名来访问。
2)不需要初始化类就可以访问静态变量。
2.2静态方法
1)Java 中的静态方法在编译时解析,因为静态方法不能被重写(方法重写发生在运行时阶段,为了多态)。
2)抽象方法不能是静态的。
3)静态方法不能使用 this 和 super 关键字。
4)成员方法可以直接访问其他成员方法和成员变量。
5)成员方法也可以直接方法静态方法和静态变量。
6)静态方法可以访问所有其他静态方法和静态变量。
7)静态方法无法直接访问成员方法和成员变量。
2.3静态代码块
1)一个类可以有多个静态代码块。
2)静态代码块的解析和执行顺序和它在类中的位置保持一致。
2.4静态内部类
1)静态内部类不能访问外部类的所有成员变量。
2)静态内部类可以访问外部类的所有静态变量,包括私有静态变量。
3)外部类不能声明为 static。
1.从使用上说
1.1final变量
final变量有成员变量或者是本地变量(方法内的局部变量),在类成员中final经常和static一起使用,作为类常量使用。其中类常量必须在声明时初始化,final成员常量可以在构造函数初始化。
1.2final方法
final方法表示该方法不能被子类的方法重写
1.3final类
final类不能被继承,final类中的方法默认也会是final类型的,java中的String类和Integer类都是final类型的。
2.使用细节
1)final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误。final变量一旦被初始化后不能再次赋值。
2)本地变量必须在声明时赋值。 因为没有初始化的过程
3)在匿名类中所有变量都必须是final变量。
4)final方法不能被重写, final类不能被继承
5)接口中声明的所有变量本身是final的。类似于匿名类
6)final和abstract这两个关键字是反相关的,final类就不可能是abstract的。
7)final方法在编译阶段绑定,称为静态绑定(static binding)。
8)将类、方法、变量声明为final能够提高性能,这样JVM就有机会进行估计,然后优化。
3.final好处(为什么使用final)
1)提高了性能,JVM在常量池中会缓存final变量
2)final变量在多线程中并发安全,无需额外的同步开销
3)final方法是静态编译的,提高了调用速度
4)final类创建的对象是只可读的,在多线程可以安全共享
1.语法层面上的区别
1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。
2.设计层面上的区别
2.1抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。
举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。
2.2抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。
模板式设计:
大家都用过ppt里面的模板,如果用模板A设计了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它们的公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt B和ppt C进行改动。
辐射式设计:
比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新
1.缓冲范围-128-127
2.面试题
3.底层源码和原理
private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k = 127; } private IntegerCache() {} }1)内部使用的cache数组作为缓存数据的机制;
2)使用了low、high分别作为缓存的数值的最小值和最大值;
3)low实际上是一个固定的值-128;
4)high是可以设置的:
1.编译性语言和解释性语言概念
编译型语言:把做好的源程序全部编译成二进制代码的可运行程序。然后,可直接运行这个程序。
解释型语言:把做好的源程序翻译一句,然后执行一句,直至结束!
2.java为什么是解释性语言
虽然java也需要编译,编译成.class文件,但是并不是机器可以识别的语言,而是字节码,最终还是需要 jvm的解释,才能在各个平台执行,这同时也是java跨平台的原因。
在Java中,使用 { } 括起来的代码被称为代码块
局部代码块
构造代码块
静态代码块
在一个类中定义一个类。举例:在一个类A的内部定义一个类B,类B就被称为内部类
当发现某个方法需要,接口或抽象类的子类对象,我们就可以传递一个匿名内部类过去,来简化传统的代码
/* 游泳接口 */ interface Swimming { void swim(); } public class TestSwimming { public static void main(String[] args) { goSwimming(new Swimming() { @Override public void swim() { System.out.println("铁汁, 我们去游泳吧"); } }); } /** * 使用接口的方法 */ public static void goSwimming(Swimming swimming){ /* Swimming swim = new Swimming() { @Override public void swim() { System.out.println("铁汁, 我们去游泳吧"); } } */ swimming.swim(); } }
常见的解析工具
DOM4J: 开源组织提供了一套XML的解析的API-dom4j,全称:Dom For Java
xml解析就是从xml中获取到数据
元注解就是描述注解的注解
因为存储数据的char数组是使用final进行修饰的,所以不可变。
这是因为在StringBuffer类内,常用的方法都使用了synchronized 进行同步所以是线程安全的,然而StringBuilder并没有。这也就是运行速度StringBuilder > StringBuffer的原因了。
Java 的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法; 并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制。
HashMap采用key/value存储结构,每个key对应唯一的value,查询和修改的速度都很快,能达到O(1)的平均时间复杂度。它是非线程安全的,且不保证元素存储的顺序。key值和vaule都可以为空。
不保证元素存储的顺序
Map mp = new HashMap(); for (int i=0; i System.out.println(entry.getKey() + "-" + entry.getValue()); }结果
key1-value1 key2-value2 key0-value0 key5-value5 key6-value6 key3-value3 key4-value4 key9-value9 key7-value7 key8-value8如果想要有序,采用LinkedHashMap
jdk1.7中采用数组+链表
1.7中hashmap有一个内部类Entry,每添加一个新的键值对就将它封装到一个Entry对象中,然后放进容器中。
jdk1.8采用数组+链表+红黑树
数组元素和链表节点采用内部类Node类实现,与jdk1.7的Entry类对比,仅仅只是换了名字。而红黑树采用TreeNode类实现
1)引入红黑树的原因
加快查询速度
数组的查询效率为O(1),链表的查询效率是O(k),红黑树的查询效率是O(log k),k为桶(数组的一个元素又称作桶)中的元素个数,所以当元素数量非常多的时候,转化为红黑树能极大地提高效率。
2)转换阈值
数组长度大于等于64,且链表长度大于等于8,将链表转换成红黑树。
当红黑树中节点数量小于等于6,则将红黑树还原回链表
3)为什么转换阈值是8和6
根据泊松分布,hash碰撞发生8次的概率非常低,此时链表性能已经非常差,后序可能还会继续发生hash碰撞。转换成红黑树主要出于性能考虑。
而红黑树转链表的阈值为6,主要是因为,如果也将该阈值设置于8,那么当hash碰撞在8时,会反生链表和红黑树的不停相互激荡转换,白白浪费资源。
4)为什么采用红黑树而不是平衡二叉树
对于插入删除等操作,红黑树效率更高。原因是平衡二叉树对于平衡性的要求更高,在调整平衡的过程中消耗更大。
详解
5)补充:红黑树的介绍
是一种特殊的二叉查找树
1)hashmap采用的方法
链地址法
hashmap中的hash算法本质上分为三步:取key的hashCode值、高位运算、取模运算
jdk1.8中优化了高位运算的算法,(h = key.hashCode()) ^ (h >>> 16)主要考虑性能优化,使得数组较小的时候,也能保证考虑到高低位都参与到Hash的计算中,同时不会有太大的开销。
第三步取模运算采用h & (table.length -1)。因为HashMap底层数组的长度总是2的n次方。当length总是2的n次方时,h& (length-1)运算等价于对length取模,也就是h%length,但是&比%具有更高的效率。
2)解决hash冲突的主要方法
(1)开放定址法(2)链地址法(3)再哈希法(4)公共溢出区域法
掌上小满app(又名OKKI)下载v6.24.2 安卓版
108.1M |商务办公
星巴克中国官方版app下载v10.9.3 安卓版
138.0M |生活服务
abc reading app手机版下载v7.3.35 安卓最新版本
218.9M |学习教育
智慧联想摄像头app(更名智享家)下载v4.1.6.2 安卓最新版本
211.4M |生活服务
星通货主app下载v902 安卓版
142.5M |生活服务
火花思维官方版下载v2.1.1 安卓手机版
208.6M |学习教育
火山小视频极速版2025(改名抖音火山版)下载v33.4.0 安卓官方正版
248.5M |影音播放
泰州通app下载v2.2.2 安卓版
126.9M |商务办公
2022-06-23
2022-01-27
2022-01-20
2022-03-31
2011-04-23
2022-03-31
2022-03-31
2022-05-19
2022-07-08
2022-07-07