java基础
一、java 中==和 equals 和 hashCode 的区别
1、对象类型不同 1、equals():是超类Object中的方法。 2、==:是操作符。
2、比较的对象不同 1、equals():用来检测两个对象是否相等,即两个对象的内容是否相等。 2、==:用于比较引用和比较基本数据类型时具有不同的功能。
3、运行速度不同 1、equals():没有==运行速度快。 2、==:运行速度比equals()快,因为==只是比较引用。
4、 hashCode() 方法用于返回字符串的哈希码。
hashCode 方法的常规约定如下:
- 程序执行期间只要对象 equals 方法比较操作所用到的信息没有被修改,则对这同一个对象无论调用多次 hashCode 方法都必须返回同一个整数。
- 如果两个对象根据 equals 方法比较是相等的则调用这两个对象中任意一个对象的 hashCode 方法都必须产生同样的整数结果。
- 如果两个对象根据 equals 方法比较是不相等的,则调用这两个对象中任意一个对象的 hashCode 方法不一定要产生相同的整数结果(尽量保证不相等的对象产生截然不同的整数结果是可以提高散列表性能的)。
二、int、char、long 各占多少字节数
* byte
1字节
最小值是 -128(-2^7);
最大值是 127(2^7-1);
* boolean 至少1字节
这种类型只作为一种标志来记录 true/false 情况;
* short 2字节
最小值是 -32768(-2^15);
最大值是 32767(2^15 - 1);
* char 2字节
最小值是 \u0000(即为0);
最大值是 \uffff(即为65,535);
* int 4字节
最小值是 -2,147,483,648(-2^31);
最大值是 2,147,483,647(2^31 - 1);
* float 4字节 单精度浮点数字长32位,尾数长度23,指数长度8,指数偏移量127;
* long 8字节
最小值是 -9,223,372,036,854,775,808(-2^63);
最大值是 9,223,372,036,854,775,807(2^63 -1);
* double 8字节 双精度浮点数字长64位,尾数长度52,指数长度11,指数偏移量1023;
三、int 与 integer 的区别
-
Integer是int的包装类,int则是java的一种基本数据类型
-
Integer变量必须实例化后才能使用,而int变量不需要
-
Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值 。
-
Integer的默认值是null,int的默认值是0
四、谈谈对 java 多态的理解
-
面向对象编程有三大特性:封装、继承、多态。
-
封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。
-
继承是为了重用父类代码。两个类若存在IS-A的关系就可以使用继承。同时继承也为实现多态做了铺垫。
-
多态性:顾名思义就是拥有“多种形态”的含义,是指属性或方法在子类中表现为多种形态。
-
多态的好处:可替换性、可扩充性、接口性、灵活性、简化性。
五、String、StringBuffer、StringBuilder 区别
-
String:字符串常量,String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,这样不仅效率低下,而且大量浪费有限的内存空间。
-
StringBuffer: 字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用 StringBuffer,如果想转成 String 类型,可以调用 StringBuffer 的 toString() 方法。
-
StringBuilder :字符串变量(非线程安全)。在内部,StringBuilder 对象被当作是一个包含字符序列的变长数组。
它是一个可变的字符序列,是 JDK5.0 新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。
小结
- 如果要操作少量的数据用 String;
- 多线程操作字符串缓冲区下操作大量数据 StringBuffer;
- 单线程操作字符串缓冲区下操作大量数据 StringBuilder。
六、什么是内部类?内部类的作用
- 内部类可以分为多种;主要以下4种:静态内部类,成员内部类,局部内部类,匿名内部类
1、静态内部类
静态内部类是指被声明为static的内部类,他可以不依赖内部类而实例,而通常的内部类需要实例化外部类,从而实例化。静态内部类不可以有与外部类有相同的类名。不能访问外部类的普通成员变量,但是可以访问静态成员变量和静态方法(包括私有类型)
2、成员内部类
一个 静态内部类去掉static 就是成员内部类,他可以自由的引用外部类的属性和方法,无论是静态还是非静态。但是不可以有静态属性和方法
3、局部内部类
定义在一个代码块的内类,他的作用范围是所在代码块,是内部类中最少使用的一类型。局部内部类跟局部变量一样,不能被public ,protected,private以及static修饰,只能访问方法中定义final类型的局部变量
4、匿名内部类(实现接口的匿名内部类、匿名子类[继承父类])
匿名内部类是一种没有类名的内部类,不使用class,extends,implements,没有构造函数,他必须继承其他类或实现其他接口。匿名内部类的好处是使代码更加简洁,紧凑,但是带来的问题是易读性下降。
- 内部类好处
1、每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整,
2、方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
3、方便编写事件驱动程序
4、方便编写线程代码
七、抽象类和接口区别
1、抽象类要被子类继承,接口要被类实现。
2、接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现。
3、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
4、接口是设计的结果,抽象类是重构的结果。
3、一个类只能继承一个抽象类,而一个类却可以实现多个接口。
什么时候使用抽象类和接口:
1、如果你拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类吧。
2、如果你想实现多重继承,那么你必须使用接口。由于Java不支持多继承,子类不能够继承多个类,但可以实现多个接口。因此你就可以使用接口来解决它。
3、如果基本功能在不断改变,那么就需要使用抽象类。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。
java高级
一、哪些情况下的对象会被垃圾回收机制处理掉?
- 所有没有被使用的对象需要被回收。
二、讲一下常见编码方式?
- 什么是编码:
编码是从一种形式或格式转换为另一种形式的过程也称为计算机编程语言的代码简称编码。
计算机中存储信息的最小单元是一个字节,即8个bit。
常见编码方式
- ASCII码:共有128个,用一个字节的低7位表示。
- ISO8859-1:在ASCII码的基础上涵盖了大多数西欧语言字符,仍然是单字节编码,它总共能表示256个字符。
- GB2312:全称为《信息交换用汉字编码字符集基本集》,它是双字节编码,总的编码范围是A1F7;A1A9 ·符号区 B0~F7 汉字区。
- GBK:数字交换用汉字编码字符集》,它可能是单字节、双字节或者四字节编码,与GB2312编码兼容。
- UTF-16:具体定义了Unicode字符在计算机中的存取方法。采用2字节来表示Unicode转化格式,它是定长的表示方法,不论什么字符都可以用两个字节表示。
- UTF-8:UTF-8采用一种变长技术,每个编码区域有不同的字码长度,不同的字符可以由1至6个字节组成;如果一个字节,最高位为0,表示这是一个ASCII字符(00至7F)如果一个字节,以11开头,连续的1的个数暗示这个字符的字节数
三、utf-8 编码中的中文占几个字节;int 型几个字节?
中文utf是占有3或4个字节,英文字母占1个字节,int占4个字节
四、
五、Java异常体系
1、Exception的体系结构图
2、Throwable、Error、Exception、RuntimeException之间的区别和关系
Throwable:Throwable类是Java语言中所有错误、异常的父(超)类。他的两个子类是Error类和Exception类。
Error:Error类是Throwable类的子类,也就是程序无法处理的错误。Error总是不可受检的,经常用来表示系统错误或低层资源的错误,如果可能的话,应该在系统级被捕获。
Exception:Exception 类及其子类是Throwable 的一种形式,分为Unchecked Exception和Checked Exception,它指出了合理的应用程序想要捕获的条件。
RuntimeException:RuntimeException是Exception的子类,属于UncheckedException是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。可能在执行方法期间抛出但未被捕获的RuntimeException ,运行时异常的任何子类都无需在 throws 子句中进行声明。也就是说RuntimeException可以不抛给上级调用者处理,可以直接抛给JVM处理。但是最好也try catch一下。
六、谈谈你对解析与分派的认识。
-
解析
Java中方法调用的目标方法在Class文件里面都是常量池中的符号引用,在类加载的解析阶段,会将其中的一部分符号引用转化为直接引用。这种解析的前提是:方法在程序真正运行之前就有一个可以确定的调用版本,并且这个方法的调用版本在运行期是不可改变的,即“编译期可知,运行期不可变”,这类目标的方法的调用称为解析(Resolve)。
只要能被invokestatic和invokespecial指令调用的方法,都可以在解析阶段中确定唯一的调用版本,符合条件的有静态方法(invokestatic指令)、私有方法、实例构造方法、父类方法(这3个是invokespecial指令),它们在类加载的的解析阶段就会将符号引用解析为该方法的直接引用。 -
分派
分派是多态性的体现,Java虚拟机底层提供了我们开发中“重载”(Overload)“和重写”(Override)的底层实现。其中重载属于静态分派,而重写则是动态分派的过程。
解析调用一定是个静态的过程,在编译期就完全确定,在类加载的解析阶段就将涉及的符号引用全部转变为可以确定的直接引用,不会延迟到运行期再去完成。
七、修改对象 A 的 equals 方法的签名,那么使用 HashMap 存放这个对象 实例的时候,会调用哪个 equals 方法?
会调用对象对象的equals方法。
“==”如果是基本类型的话就是看他们的数据值是否相等就可以。
如果是引用类型的话,比较的是栈内存局部变量表中指向堆内存中的指针的值是否相等
“equals”如果对象的equals方法没有重写的话,equals方法和“==”是同一种。
hashcod是返回对象实例内存地址的hash映射。
理论上所有对象的hash映射都是不相同的。
问题:
1.你用过hashmap么?
答:是的,然后回答HashMap的一些特性,譬如HashMap可以接受null键值和值,而Hashtable则不能;HashMap是非synchronized;HashMap很快;以及HashMap储存的是键值对等等。
2.你知道hashmap的工作原理么?
答:HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。”这里关键点在于指出,HashMap是在bucket中储存键对象和值对象,作为Map.Entry。这一点有助于理解获取对象的逻辑。如果你没有意识到这一点,或者错误的认为仅仅只在bucket中存储值的话,你将不会回答如何从HashMap中获取对象的逻辑。这个答案相当的正确,也显示出面试者确实知道hashing以及HashMap的工作原理。但是这仅仅是故事的开始,当面试官加入一些Java程序员每天要碰到的实际场景的时候,错误的答案频现。
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
3.当两个对象的hashcode相同会发生什么?
因为即使hashcode相同,但是equals不同。
因为hashcode相同,所以它们的bucket位置相同,‘碰撞’会发生。因为HashMap使用链表存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在链表中。
4.如果两个键的hashcode相同,你如何获取值对象?
当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置,然后获取值对象。
5.面试官提醒他如果有两个值对象储存在同一个bucket?
将会遍历链表直到找到值对象
6.因为你并没有值对象去比较,你是如何确定确定找到值对象的?
找到bucket位置之后,会调用keys.equals()方法去找到链表中正确的节点,最终找到要找的值对象。
网友评论