问题汇总
1.JVM/JRE/JDK三者有什么区别?
2.String str = new String(“abc”) 创建了几个字符串对象?
3.深拷贝和浅拷贝区别是什么?
4.==与equals的区别?
5.重写equals()方法为什么一定要重写hashCode()方法?
6.值传递和引用传递的区别的什么?为什么说Java中只有值传递?
7.什么是反射?有哪些实现方式?有哪些应用?
8.简述面向对象设计原则?
9.使用泛型的好处?什么是类型擦除?
10.你知道内部类吗?
1.JVM/JRE/JDK三者有什么区别?
一张图解决
2.String str = new String(“abc”) 创建了几个字符串对象?
答案:1 个或者 2 个。
如果字符串常量池中已经有"abc"存在,这种情况只需要新建1个对象,否则就需要新建2个对象。
当字符串常量池没有 “abc”,此时会创建如下两个对象:
一个是字符串字变量 “abc” 所对应的、驻留(intern)在一个全局共享的字符串常量池中的实例,此时该实例也是在堆中,字符串常量池只存放引用。
另一个是通过 new String() 创建并初始化的,内容与"abc"相同的实例,也是在堆中。
3.深拷贝和浅拷贝区别是什么?
我们都知道基本数据类型:数据直接存储在栈中;引用数据类型:存储在栈中的是对象的引用地址,真实的对象数据存放在堆内存里。
浅拷贝:对于基础数据类型:直接复制数据值;对于引用数据类型:只是复制了对象的引用地址,新旧对象指向同一个内存地址,修改其中一个对象的值,另一个对象的值随之改变。
深拷贝:对于基础数据类型:直接复制数据值;对于引用数据类型:开辟新的内存空间,在新的内存空间里复制一个一模一样的对象,新老对象不共享内存,修改其中一个对象的值,不会影响另一个对象。
深拷贝相比于浅拷贝速度较慢并且花销较大。
4.==与equals的区别?
比较的是栈中的值,我们知道,对于基本数据类型是存储在栈中,所以对于基本数据类型用进行比较是直接比较数值,而对于引用类型来说,栈中存放的只是对象的引用地址,真正的对象实例存放在堆中
equals()方法是Object类的方法,在Object类中的equals()方法体内实际上返回的就是使用==进行比较的结果,所以我们通常都会对equals方式自动化重写,使其比较的是对象的内容
5.重写equals()方法为什么一定要重写hashCode()方法?
hashCode通用的约定是无论何时,对同一个对象调用hashCode()都应该产生同样的值
重写 hashcode() 方法的原因,简单的说就是:为了保证是同一个对象,在 equals 比较相同的情况下 hashcode值必定相同
当我们向一个Hash结构的集合中添加某个元素,集合会首先调用hashCode方法,这样就可以直接定位它所存储的位置,若该处没有其他元素,则直接保存。若该处已经有元素存在,就调用equals方法来匹配这两个元素是否相同,相同则不存,不同则链到后面(如果是链地址法)。在面试中被问到并发知识的时候,大多都会被问到“请你说一下自己对于AQS原理的理解”。下面给大家一个示例供大家参加,面试不是背题,大家一定要假如自己的思想,即使加入不了自己的思想也要保证自己能够通俗的讲出来而不是背出来。在此我向大家推荐一个架构学习交流圈。交流学习伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
先调用hashCode,唯一则存储,不唯一则再调用equals,结果相同则不再存储,结果不同则散列到其他位置。因为hashCode效率更高(仅为一个int值),比较起来更快。
如果重写equals不重写hashCode会怎样?
由于默认的 hashcode 方法是根据对象的内存地址经哈希算法得来的,两个不同的对象的hashCode一定不一样,那么执行equals,结果为true,HashSet或HashMap的键会放入值相同值的对象。
6.值传递和引用传递的区别的什么?为什么说Java中只有值传递?
值传递:指的是在方法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相关了。
引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的是引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。
基本类型作为参数被传递时肯定是值传递;引用类型作为参数被传递时也是值传递,只不过“值”为对应的引用。
7.什么是反射?有哪些实现方式?有哪些应用?
反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。在面试中被问到并发知识的时候,大多都会被问到“请你说一下自己对于AQS原理的理解”。下面给大家一个示例供大家参加,面试不是背题,大家一定要假如自己的思想,即使加入不了自己的思想也要保证自己能够通俗的讲出来而不是背出来。在此我向大家推荐一个架构学习交流圈。交流学习伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
实现方式:
1 Class.forName(“类的路径”);当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。
Class clz = Class.forName("java.lang.String");
2 类名.class。这种方法只适合在编译前就知道操作的 Class。
Class clz = String.class;
3 对象名.getClass()。
String str = new String("Hello"); Class clz = str.getClass();
4,.如果是基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象。
实际应用
第一种:JDBC 的数据库的连接
在JDBC 的操作中,如果要想进行数据库的连接,则必须按照以上的几步完成
通过Class.forName()加载数据库的驱动程序 (通过反射加载,前提是引入相关了Jar包);
通过 DriverManager 类进行数据库的连接,连接的时候要输入数据库的连接地址、用户名、密码;
通过Connection 接口接收连接。
第二种:Spring 框架的使用,最经典的就是xml的配置模式。
Spring 通过 XML 配置模式装载 Bean 的过程:
将程序内所有 XML 或 Properties 配置文件加载入内存中;
Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息;
使用反射机制,根据这个字符串获得某个类的Class实例;
动态配置实例的属性。
Spring这样做的好处是:
不用每一次都要在代码里面去new或者做其他的事情;
以后要改的话直接改配置文件,代码维护起来就很方便了;
有时为了适应某些需求,Java类里面不一定能直接调用另外的方法,可以通过反射机制来实现。
8.简述面向对象设计原则?
1 开闭原则(核心原则):对扩展开放,对修改关闭
2 里式替换原则:继承必须确保父类所拥有的性质在子类中任然成立(子类不要重写父类非抽象方法)
3 依赖倒置原则:面向接口编程,减低耦合性(高层不依赖低层,)象不依赖细节)
4 单一职责原则:控制类的颗粒度大小,将对象解耦,提高其内聚性(管的事不要太多)
5 接口隔离原则:为各个类建立它们需要的专用接口
6 迪米特法则:一个软件实体应当尽可能少地与其他实体发生相互作用(只与你的直接朋友交谈,不跟“陌生人”说话)
7 合成复用原则:尽量先使用组合和聚合等关联关系,其次才考虑继承关系实现
9.使用泛型的好处?什么是类型擦除?
1 类型安全
泛型的主要目标是提高 Java 程序的类型安全
编译时期就可以检查出因 Java 类型不正确导致的 ClassCastException 异常
符合越早出错代价越小原则
2 消除强制类型转换
泛型的一个附带好处是,使用时直接得到目标类型,消除许多强制类型转换
所得即所需,这使得代码更加可读,并且减少了出错机会
类型擦除:
泛型是一种语法糖,泛型这种语法糖的基本原理是类型擦除。Java中的泛型基本上都是在编译器这个层次来实现的,也就是说:泛型只存在于编译阶段,而不存在于运行阶段。在编译后的 class 文件中,是没有泛型这个概念的。
10.你知道内部类吗?
1.匿名内部类
没有名字的内部类
匿名内部类必须继承一个抽象类或者实现一个接口。
匿名内部类不能定义任何静态成员和静态方法。
当所在的方法的形参需要被匿名内部类使用时,必须声明为 final。
匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
2.局部内部类
定义在方法中的内部类,定义在实例方法中的局部类可以访问外部类的所有变量和方法,定义在静态方法中的局部类只能访问外部类的静态变量和方法,创建方式,new 内部类(),注意局部只能在方法里使用
3.成员内部类
成员位置上的非静态类,可以访问外部类所有的变量和方法,创建方式,外部类实例.new 内部类()
4.静态内部类
可以且只能访问外部类的所有静态变量,静态内部类的创建方式,直接new 静态内部类
package java基础;import java.util.Comparator;public class OuterClass { private int age;
private String nameString;
private static int flag = 1;
public OuterClass () {
super();
// TODO Auto-generated constructor stub
}
public OuterClass (int age, String nameString)
{
super();
this.age = age;
this.nameString = nameString;
}
public void testInternalClass()
{
/** * @author ASUS * 局部内部类 */ class Duck {
public void prints() { System.out.println(age+"/"+nameString);
}
}
Duck d = new Duck();
d.prints();
}
/** * @author ASUS * 成员内部类 */
class Monkey
{
public void prints()
{
System.out.println(age+"/"+nameString);
}
}
/** * @author ASUS * 静态内部类 */
static class Buck
{
public void prints()
{
System.out.println(flag);
}
}
public static void main(String[] args)
{
// TODO Auto-generated method stub
Monkey monkey = new OuterClass (12,"Sun wu kon!").new Monkey(); monkey.prints();
OuterClass outerClass = new OuterClass (13,"Sun wu jing!"); outerClass.testInternalClass();
System.out.println();
//匿名内部类
int result = new Comparator<String>()
{
@Override
public int compare(String o1, String o2)
{
// TODO Auto-generated method stub
return o1.compareTo(o2);
}
}.compare("a", "b");
System.out.println(result);
//静态内部类直接new,不需要外部类实例
Buck buck = new Buck();
buck.prints(); }}
内部类优点
1 一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据!
2 内部类不为同一包的其他类所见,具有很好的封装性;
3 内部类有效实现了“多重继承”,优化 java 单继承的缺陷。
4 匿名内部类可以很方便地定义回调。
注意:局部内部类和匿名内部类访问局部变量的时候,变量必须要加上final
互联网一线大厂面试题库
百度篇:链接:https://pan.baidu.com/s/140KuFVKGWcV6E6n52MdNXQ
提取码:b0p5