备战Java面试【每日十道面试题系列】 --基础篇Day2
2021/7/23 1:06:46
本文主要是介绍备战Java面试【每日十道面试题系列】 --基础篇Day2,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
因为热爱所以坚持,因为热爱所以等待。熬过漫长无戏可演的日子,终于换来了人生的春天,共勉!!!
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方法来匹配这两个元素是否相同,相同则不存,不同则链到后面(如果是链地址法)。
- 先调用hashCode,唯一则存储,不唯一则再调用equals,结果相同则不再存储,结果不同则散列到其他位置。因为hashCode效率更高(仅为一个int值),比较起来更快。
-
如果重写equals不重写hashCode会怎样?
由于默认的 hashcode 方法是根据对象的内存地址经哈希算法得来的,两个不同的对象的hashCode一定不一样,那么执行equals,结果为true,HashSet或HashMap的键会放入值相同值的对象。
6.值传递和引用传递的区别的什么?为什么说Java中只有值传递?
- 值传递:指的是在方法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相关了。
- 引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的是引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。
基本类型作为参数被传递时肯定是值传递;引用类型作为参数被传递时也是值传递,只不过“值”为对应的引用。
7.什么是反射?有哪些实现方式?有哪些应用?
反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。
- 实现方式:
-
Class.forName(“类的路径”);当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。
Class clz = Class.forName("java.lang.String");
-
类名.class。这种方法只适合在编译前就知道操作的 Class。
Class clz = String.class;
-
对象名.getClass()。
String str = new String("Hello"); Class clz = str.getClass();
-
如果是基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象。
- 实际应用
第一种:JDBC 的数据库的连接
-
在JDBC 的操作中,如果要想进行数据库的连接,则必须按照以上的几步完成
-
通过Class.forName()加载数据库的驱动程序 (通过反射加载,前提是引入相关了Jar包);
-
通过 DriverManager 类进行数据库的连接,连接的时候要输入数据库的连接地址、用户名、密码;
-
通过Connection 接口接收连接。
第二种:Spring 框架的使用,最经典的就是xml的配置模式。
Spring 通过 XML 配置模式装载 Bean 的过程:
-
将程序内所有 XML 或 Properties 配置文件加载入内存中;
-
Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息;
-
使用反射机制,根据这个字符串获得某个类的Class实例;
-
动态配置实例的属性。
Spring这样做的好处是:
-
不用每一次都要在代码里面去new或者做其他的事情;
-
以后要改的话直接改配置文件,代码维护起来就很方便了;
-
有时为了适应某些需求,Java类里面不一定能直接调用另外的方法,可以通过反射机制来实现。
8.简述面向对象设计原则?
- 开闭原则(核心原则):对扩展开放,对修改关闭
- 里式替换原则:继承必须确保父类所拥有的性质在子类中任然成立(子类不要重写父类非抽象方法)
- 依赖倒置原则:面向接口编程,减低耦合性(高层不依赖低层,)象不依赖细节)
- 单一职责原则:控制类的颗粒度大小,将对象解耦,提高其内聚性(管的事不要太多)
- 接口隔离原则:为各个类建立它们需要的专用接口
- 迪米特法则:一个软件实体应当尽可能少地与其他实体发生相互作用(只与你的直接朋友交谈,不跟“陌生人”说话)
- 合成复用原则:尽量先使用组合和聚合等关联关系,其次才考虑继承关系实现
9.使用泛型的好处?什么是类型擦除?
-
类型安全
-
泛型的主要目标是提高 Java 程序的类型安全
-
编译时期就可以检查出因 Java 类型不正确导致的 ClassCastException 异常
-
符合越早出错代价越小原则
-
-
消除强制类型转换
-
泛型的一个附带好处是,使用时直接得到目标类型,消除许多强制类型转换
-
所得即所需,这使得代码更加可读,并且减少了出错机会
-
类型擦除:
泛型是一种语法糖,泛型这种语法糖的基本原理是类型擦除。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(); } }
内部类优点
- 一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据!
-
内部类不为同一包的其他类所见,具有很好的封装性;
-
内部类有效实现了“多重继承”,优化 java 单继承的缺陷。
-
匿名内部类可以很方便的定义回调。
注意:局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final
最后:创作不易,喜欢的话请给个赞吧,为了保证内容准确查阅了大量的资料,力求严谨准确,如果你也和我一样备战面试,关注我,持续更新,一起加油吧,给努力的自己点个赞!!!
参考资料
书籍:
java核心技术、java编程思想
博客:https://blog.csdn.net/weixin_43591980/article/details/117215356
https://blog.csdn.net/weixin_44259720/article/details/88414828
https://blog.csdn.net/qq_36470686/article/details/83444483
这篇关于备战Java面试【每日十道面试题系列】 --基础篇Day2的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-22项目:远程温湿度检测系统
- 2024-12-21《鸿蒙HarmonyOS应用开发从入门到精通(第2版)》简介
- 2024-12-21后台管理系统开发教程:新手入门全指南
- 2024-12-21后台开发教程:新手入门及实战指南
- 2024-12-21后台综合解决方案教程:新手入门指南
- 2024-12-21接口模块封装教程:新手必备指南
- 2024-12-21请求动作封装教程:新手必看指南
- 2024-12-21RBAC的权限教程:从入门到实践
- 2024-12-21登录鉴权实战:新手入门教程
- 2024-12-21动态权限实战入门指南