文章目录
- 什么是面向对象?
- 面向对象有哪些特征?
- 面向对象和面向过程的区别?
- 重载和重写的区别?
- Java中,什么是构造方法?什么是构造方法重载
- JDK、JRE、JVM分别是什么关系?
- 什么是字节码?采用字节码的最大好处?
- JAVA的基本数据类型
- 什么是值传递和引用传递?
- 是否可以在static环境中访问非static变量?
- String、StringBuffer、StringBuilder的区别?
- String 不可变,StringBuffer\StringBuilder 可变?
- 什么是自动拆装箱?
- equals与==的区别?
- final、finally、finalize的区别?
- 抽象类和接口有什么区别?
- 类的实例化顺序?
- 什么是JAVA IO?
- 什么是JAVA序列化?
- 如何序列化?
- 序列化中如果有些字段不需要进行序列化?
- 如何实现对象克隆?
- 反射的用途及实现?
- Class.forName和ClassLoader的区别?
- JAVA创建对象的几种方式?
什么是面向对象?
面向对象是一种思想,世间万物都可以看做是一个对象,这里只讨论面向对象编程(OOP),JAVA是一个支持高并发、基于类和面向对象的计算机编程语言。面向对象软件开发具有以下的优点:
- 代码开发模块化,更容易维护和修改
- 代码复用性、可靠性和灵活性增强
- 代码可读性提高
面向对象有哪些特征?
总的来概括是有四大类:封装、继承、多态、抽象
- 封装:
封装指的是给对象提供了隐藏内部特性和行为的能力,对象提供一些能被其他对象访问的方法来改变它内部的数据。在Java中,有4种修饰符 default、public、private、protected。每一种修饰符给其他的位于同一个包或者不同包下面对象赋予了不同的访问权限。 - 继承
继承给对象提供了从基类(父类)获取字段和方法的能力,继承提供了代码的重用性,也可以在不修改类的情况下给现存的类添加新的属性 - 多态
指的是多个不同的底层实现类在实现同一个相同数据类型的一种能力。一个多态类型的操作,可以应用到其他类型的实现了同一数据类型的接口上去。 - 抽象
把想法从具体的实例中分离出来,可以根据需求和功能的不同来创建子类进行实现
面向对象和面向过程的区别?
面向过程:
- 优点:性能比面向对象高,避免了类调用时需要的实例化,但是开销交大,消耗资源。
- 缺点:不易于维护、复用和扩展
面向过程:
- 优点:易维护、复用和扩展,由于面向对象的4大特性,可以设计出低耦合的系统,使系统更加灵活
- 缺点:性能比面向过程低
重载和重写的区别?
重写 override:
- 方法名、参数、返回值相同
- 子类不能缩小父类的访问权限、子类不能抛出比父类方法多的异常
- 方法被final修饰的不能进行重写
重载overload
- 参数类型、个数、顺序至少有一个不相同
- 不能重载只有返回值不同的方法名
Java中,什么是构造方法?什么是构造方法重载
- 构造方法
当一个新对象被创建的时候,构造方法会被Java编译器默认初始化耦合无参的构造方法 - 构造方法重载
与方法重载很相似,可以为一个类创建多个构造方法,但是每个构造方法的参数列表必须保证是唯一的
JDK、JRE、JVM分别是什么关系?
- JDK为java开发的工具包,包含java程序所需要的编译、运行等环境。简单来说就是JDK包含JRE包含JVM
- JRE为java的运行环境,包含了java的虚拟机(JVM)和丰富的系统类库。系统类库为java提前封装好的功能类,拿来即用,大大提高了开发的效率
- JVM为java的虚拟机,提供了字节码文件的运行环境
什么是字节码?采用字节码的最大好处?
java中引进了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的机器。在这台虚拟的机器在任何一个平台都提供编译程序一个共同的接口
编译程序之后需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换成特定系统的机器码执行。在java中,这种供虚拟机理解的代码叫字节码,它不面向任何特定的处理器,只面向虚拟机。
每一种平台的解释器都是不同的,但是实现的虚拟机是相同的。Java程序通过编译器编译成字节码,字节码在由虚拟机进行解释,把每一条执行的字节码发送给解释器,解释器再翻译成特定操作系统的机器码进行执行,所以说java是一门跨平台的语言。
JAVA的基本数据类型
JAVA支持的数据类型包括基本数据类型和引用数据类型
基本数据类型如下:
- 整数型:byte、short、int、long
- 字符型:char
- 浮点型:float、double
- 布尔型:boolean
引用数据类型声明的变量实际上市在内存中的一个引用地址,实体是在堆中:
- 引用类型包含类、接口、数组等
- String是引用类型不是基本类型
什么是值传递和引用传递?
- 值传递是正对于基本数据类型的变量而言,传递的是该变量的一个副本,改变这个副本不影响原值
- 引用传递,一般是指对象型的变量,传递的是该对象子堆内存中的一个地址,而不是源对象
是否可以在static环境中访问非static变量?
static变量在java中属于类的,他在所有的实例中是一样的。当类被java虚拟机加载的时候,会对static变量进行初始化复制(进行默认值赋值)
如果不尝试用实例来进行访问非static的变量,编译器报错,是因为此时这些变量还没有真正意义上的创建出来,还未与实例进行管理
// 此时在java虚拟机进行类加载准备阶段赋值时,默认赋值为0
private static int a = 1;
// 而被final修饰后,会在虚拟机中默认初始化一个ConstantValue进行赋值
private final static int a = 1;
String、StringBuffer、StringBuilder的区别?
- String:只读字符串,因为被final修饰所以String引用的字符串内容是不能被修改的。每次对String类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String对象
- StringBuffer/StringBuilder:标识字符串对象可以直接进行修改。StringBuffer每次都是对自身对象进行操作,而不是生成新的对象并改变对象的引用。StringBuffer因为被synchronized修饰,所以相比于StringBuilder会线程不安全,性能也仅仅差了百分10~15左右
一道常见的面试题
// 创建了几个对象
String s = new String("a");
// 首先,字符串a会在字符串常量池中寻找,若找不到则会创建一个对象
// 然后,因为有new关键字,所以会在内存中创建一个String对象,并将其返回给s
// 所以答案显然是1个或者2个
String 不可变,StringBuffer\StringBuilder 可变?
- String类中使用了final关键字修饰字符串数组,所以String对象是不可变的
// String.java
private final char[] value;
- StringBuffer\StringBuilder都是继承AbstractStringBuilder类,而在AbstractStringBuilder中也是使用字符串数组,但是没有被final修饰,所以是可变的
// AbstractStringBuilder.java
private char[] value;
什么是自动拆装箱?
就是基本数据类型和引用类型之间的相互转换
equals与==的区别?
- 值类型(int,char,long,boolean等)都是用==判断相等性
- 对象引用的话:
==判断引用所指的对象是否是 同一个,也就是比较内存中指向的地址是否相同
equals方法,用于判断对象的值是否相等
final、finally、finalize的区别?
- final:是修饰符关键字,如果一个类被声明为final,意味它不能在派生出新的子类,不能作为父类被继承。因此一个类不能被声明为abstract又被声明为final。被声明为final的类在使用中不被改变,并且必须在声明时给定初始值。
- finally:异常处理中提供来执行清楚操作。如果抛出一个异常,则会匹配相对应的catch子句进行执行,最后控制会进入finally块
- finalize:方法名。java允许使用该方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法由垃圾收集器在确认这个对象没有被引用时对这个对象调用
抽象类和接口有什么区别?
从设计角度来说:抽象类是对类的抽象,是一种模板的设计;接口是行为的抽象,是一种行为的规范
不同点:
- 接口中的所有方法隐含的都是抽象,而抽象类则可以同时包含抽象和非抽象方法
- 类可以实现多个接口,但是只能继承一个抽象类
- 接口中的变量默认都是final的,抽象类可以包含非final的变量
- 接口中的成员函数默认都是public的,抽象类的可以死private,protected或者是public
- 接口是绝对抽象,不可以实例化。抽象类也不可以实例化
类的实例化顺序?
- 父类静态变量
- 父类静态代码块
- 子类静态变量
- 子类静态代码块
- 父类非静态变量
- 父类构造函数
- 子类非静态变量
- 子类构造函数
什么是JAVA IO?
java io具体的操作分为面向字节流(byte)和面向字符流(character)两种方式。
1.字节流:
InputStream(输入流)
OutputStream(输出流)
2.字符流:
Reader(读取)
Writer(写出)
什么是JAVA序列化?
序列化其实就是一种用来处理对象流的机制,所谓的对象流也就是将对象的内容进行流化:
- 可以对流化后的对象进行读写操作,也可将流化后的对象传输与网络中
- 序列化是为了解决在对对象流进行读写操作时引发的问题
如何序列化?
1.使用java内置的序列化方式,实现Serializable接口
然后使用一个输出流:FileOutputStream来构造一个ObjectOutputStream对象
使用writeObject方法就可以把需要实例化的对象写出保存
2.反序列化:恢复可以使用输入流进行恢复
序列化中如果有些字段不需要进行序列化?
可以使用transient关键字修饰
如何实现对象克隆?
- 实现Cloneable接口,重写Object类中的clone()方法,可以实现浅克隆
- 实现Serializable接口,通过对象的序列化和反序列化始实现克隆。深克隆
反射的用途及实现?
- 在运行时构造一个类的对象
- 判断一个类所具有的成员变量和方法
- 调用一个对象的方法
- 生成动态代理
反射的应用很多:例如
- spring中ioc基于反射创建对象和设置依赖属性
- spring mvc的请求调用对应的方法
Class.forName和ClassLoader的区别?
- Class.forName:除了将类的.class文件加载到jvm中,还会对类进行解释,执行类中的static块
- classLoader只会干一件事情,就是将.class文件加载到jvm,不会执行static中的内容,只有在newInstance才会去执行static块
JAVA创建对象的几种方式?
- 使用new关键字创建对象
- 使用class类的newInstance方法(反射机制)
- 使用Constructor类的newInstance方法(反射机制)
- 使用clone方法
- 使用反序列化创建