java基面试础知识详解
面向对象的三大特性
1)封装
就是把同一类事物的属性和方法归到同一个类中,方便使用
防止该类的代码和数据被外部类定义的代码随意访问
要访问该类的数据和代码必须通过严格的方法控制
封装的主要功能在于我们能修改自己的实现代码,而不用修改哪些调用程序的代码片段。
优点:减少耦合,类内部自由修改,可以对类成员变量进行更精确的控制,隐藏信息、实现细节。
最佳实践:
为了实现良好的封装,通常将类的成员变量声明为private ,通过public的set和get方法完成对属性的操作
2)继承
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法
特性:
子类拥有父类的非private属性,方法
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展
子类可以用自己的方式实现父类的方法
java的继承是单继承
关键字:extends
3)多态
封装和继承几乎都是为多态而准备的
多态是同一个行为具有多个不同表现实行或形态的能力
多态是一个接口,使用不同的实例而执行不同的操作
多态存在的三个必要条件:
继承
重写
父类引用指向子类对象
重载和重写区别
重写(Override)
重写是子类对付类的允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变。 子类根据需要实现自己的方法
重载(Overload) 是在一个类里面,方法名字相同,而参数不同(个数和类型不同),返回类型可以相同也可以不同 最常用的就是构造器的重载
方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性的表现。
重写发生在子类和父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好的访问,不能比父类被重写方法声明更多的异常。—运行时多态
重写原则: 参数列表必须完全与被重写方法的一致,返回类型必须完全与被重写的方法的返回类型一致 构造方法不能被重写,声明为final的方法不能被重写,声明为static的方法不能被重写,但是能够被再次申明
访问权限不能比父类中被重写的方法的访问权限更低。
重写的父类方法能够抛出任何非强制异常(也叫非运行异常),无论被重写的方法是否抛出异常,但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明更广泛的强制性异常,反之则可以。
多态的实现机制
多态允许基类(父类)指针或引用指向派生类(子类)的对象,而在具体访问方法时实现动态绑定。
编译时多态(重载)
运行时多态(重写)
多态是针对类的方法而言的,对于类的成员变量是定义的时候确定的,即编译的时候就确定的。
是否可以继承String类
String是final类型的,所以不能被继承 java类支持多继承吗?可以实现多个接口吗?
java不支持多继承,但是类可以实现多个接口,间接的实现多继承,也可以通过内部类。
接口和抽象类有什么区别
接口和抽象类都是继承树的上层,他们的共同点如下:
1)都是上层的抽象层
2)都不能够被实例化
3)都能包含抽象的方法,这些抽象的方法用于描述类具备的功能
区别:
在抽象类中可以写非抽象的方法,从而避免在子类中重复书写,提高代码复用性–抽象类的优势,而接口当中只能有抽象的方法(jdk8之后也可以有实现方法) 一个类只能继承一个直接父类,这个父类可以是具体的类也可以是抽象类,但是一个类可以实现多个接口,接口的设计具有更大的扩展性,而抽象类的设计必须十分谨慎。
抽象级别:接口 大于 抽象类 大于 实现类
接口的设计目的:是针对类的行为进行约束,侧重于动作,而抽象类的设计目的是代码复用。 抽象类是 is a的关系,接口是has a的关系。
java中修饰符的作用域以及可见性 public :当前类、子类,同一包、其他包都可以访问 protected:当前类,子类以及同一包可以访问,其它包不可以 default:当前类和同一包可以访问,子类和其他包不可以 private:当前类可以访问,同一包、子类、其它包都不可以访问
==和equals方法的区别:
两个操作用于对象的比较,检查对象的相等性,但是区别在与equals是方法,而==是操作符 一般使用==比较原生类型如:boolean、int、char等等,使用equals比较对象 如果两个引用指向相同的对象==返回true,equals方法的返回结果依赖于具体的实现,一般重写equals方法,也重写hashcode方法, 字符串的对比使用的是equals代替==操作符
静态变量和实例变量的区别?
一个static方法内不可以调用非static方法 因为非静态方法是与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而静态方法调用不需要创建对象,也就是说,当一个静态方法被调用时,如果从一个static方法中发出对非static方法的调用,那么非静态方法关联到哪个对象上呢?这个逻辑无法成立。
static方法是静态方法,是属于类的方法;
非static方法是属于对象的方法,所以要想在static方法中调用非static方法要先创建一个对象,再由这个对象来调用。 本质是JVM加载顺序决定的,加载static方法的时候非静态方法还没有初始化,当然不能调用了
静态变量和实例变量的区别?
1)在语法定义上的区别:
静态变量前要加static关键字,而实例变量前则不加
2)在程序运行时的区别:
实例变量是属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配内存空间,才可以使用这个实例变量 静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会分配内存空间,而且只分配一次,静态变量就可以被使用了。总之,实例变量必须创建后才可以通过这个对象来使用,静态变量则直接可以使用类名来调用。
Integer和int的类型 Integer是int提供的封装类,从java5之后引入了自动装箱、拆箱机制,使得两者可以相互转换,而int是java基本数据类型 Integer默认值是null,而int默认值是0 Integer是对象,用一个引用指向这个对象,而int是基本类型,直接存储数据。
Integer提供了好多与整数相关的操作方法,例如:将一个字符串转换成整数等. Integer会有缓存
String、StringBuilder、StringBuffer:
1.执行速度方面,StringBuilder大于StringBuffer大于String String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦被创建后该对象是不可更改的,但后两者的对象是变量,是可以更改的
2.线程安全:StringBuilder是线程不安全的,而StringBuffer是线程安全的(StringBuffer中很多方法带有synchronized关键字)–同步关键字
3.总结:String:适用于少量字符串操作的情况; StringBuilder:适用于在单线程下在字符缓冲区进行大量操作的情况; StringBuffer:适用于在多线程下在字符缓冲区进行大量操作的情况
String中的常用方法有哪些: length()、isEmpty()、split()、toLowerCase()、toUpperCase() subString()、trim()、concat(“abc”)、contains(“a”)
java程序初始化的顺序是什么样子的?
一般遵循三个原则:
1.静态变量优先于非静态变量初始化,其中静态变量只初始化一次,而非静态变量可能会初始化很多次
2.父类优先子类进行初始化
3.按照成员变量定义顺序进行初始化,即使变量定义散布于方法之中,它们依然在方法调用之前(包括构造函数)先初始化。 父类静态字段初始化 父类静态代码块 子类静态字段初始化 子类静态代码块 父类普通字段初始化 父类构造代码块({//代码}) –优先于构造函数执行 父类构造函数 子类普通字段初始化 子类构造代码块 子类构造函数
很明显的看出,static字段,代码块的在执行顺序优先于非sattic、代码块,这是因为静态域是属于类的,在类加载后就一直存在,而普通域则需要创建对象才能访问。而在创建对象时,要先加载父类,然后再加载子类,因此父类的静态字段初始化和静态代码块执行优先于子类
应用:单例模式的设计(只创建一次对象的目的)
简单介绍反射机制?
反射是框架设计的灵活 使用的前提条件:必须先得到代表字节码的Class,Class类用于表示.class文件(字节码)
什么是反射机制? java反射是在运行状态中,对任意一个类,都能够知道这个类的所有属性和方法,对于任何一个对象,都能够调用它的任意一个属性和方法,这种动态获取信息以及动态调用对象的方法的功能称为java的反射机制
要想剖析一个类,必须首先获得该类的字节码文件对象,而剖析使用的就是Class类中的方法,所以先要获得每一个字节码文件对应的Class类型的对象
Class是反射的基石
1.Class是一个类,一个描述类的类,封装了描述方法的Method,描述字段的Filed,描述构造器的Constructor等属性,通过反射可以得到类的各个成分。
2.对于每个类而言,JRE都为其保留一个不变的Class类型的对象,一个Class对象包含了特定某个类的有关信息。
3.Class对象只能由JVM创建
4.一个类在JVM中只有一个Class实例 5.反射相关的类:java.lang.reflect包下
获取Class对象的三种方式:
1.Object—getClass(); 通过已知对象获取
2.任何数据类型(包括基本数据类型)都有一个静态的Class属性 通过类名.Class
3.通过Class的静态方法: Class.forName(String calssName):最常用
应用:使用JDBC连接数据库的时候,都使用的反射,一般都是通过配置文件书写连接哪个数据库,比如:mysql、oracle等,以及对应的关键信息
简单来说: 反射就是把各种java类中的各种成分映射成一个个的java对象 成员变量、方法、构造方法、构造方法、包等信息 利用反射技术可以对一个类进行剖析,把各个组成部分映射成一个个对象 核心类: Class:代表一个类 Constructor类:代表类的构造方法 Filed类:代表类的成员变量 Method:代表类的方法
反射中,Class.forName和classloader的区别:
相同点:java中Class.forName()和classloader都可以用来对类进行加载
不同点:
class.forName除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块 而classloader只做一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newinstance才会去执行static块。
calssforName(name,initialize,loader)带参函数也可以控制是否加载static块,并且只有调用了newinstance才会构造函数,来创建类的对象,jvm底层可以控制—–一般不会干预
Try catch finally的问题 当在try、catch中有return时,finally是否会执行?
总结:
1.不管有没有异常,finally中的代码都会执行
2.当try、catch中有return语句时,finally中的代码依然会继续执行
3.finally是在return后面的表达式运算之后执行的,此时并没有返回运算后的值,而是把值保存起来,不管finally对该值做了任何改变,返回的值都不会改变,依然返回保存起来的值,也就是说方法的返回值是在finally运算之前就确定了的。
4.如果return的数据是引用数据类型,而在finally中对该引用数据类型的属性值的改变起作用,try 中return返回的就是finally中改变后的属性值
5.finally代码最好不要包含return,程序会提前退出,也就是说返回的值不是try catch中的值
先执行try中的语句,包括return后面的表达式 有异常时,先执行catch中的语句,包括return 后面的表达式; 然后执行fianlly中的语句,如果finally里面有return语句,会提前退出 最后执行try 中的return,有异常执行catch中return;
在执行try catch 中的return之前一定会执行finally中的代码(如果finally存在),如果finally中有return语句,就会执行finally中的return方法,所以finally中的return语句一定会被执行的,比那一起吧finally中的retrun语句标识为一个warning
final、finally、finalize final是最终的意思,表示不能被改变,可用于成员变量、方法和类 修饰变量:变量一旦被初始化不可改变 修饰方法:方法不能被覆盖 修饰类:类不能够被继承
finally:异常处理关键字,finally中的主体总会执行,无论异常发生与否 finalize:类的finalize方法,可以告诉垃圾回收器应该执行的操作,该方法从Object继承而来,在从堆中永久删除对象之前,调用该对象的finalize方法
注意:无法确切的保证垃圾回收器何时调用该方法,也无法保证调用不同对象方法的顺序,
常见异常:
finally:finally语句块总是会被执行,它主要用于回收在try中打开的物理资源,如数据库连接,网络连接,只有finally执行完成之后,才会回来执行try catch 块中的return语句或者throw语句,如果finally中使用了throw或者return终止方法的语句,则就不会跳回执行,直接终止
throw:抛出异常 throws:用在方法签名中,用于声明该方法可能抛出的异常
java中的异常框架: Throwable (Interface) Error Exception RunTimeException
Throwable: 它是java语言中所有错误或异常的超类 它包含两个子类:Error和Exception Throwable包含了其线程创建时执行线程执行堆栈的快照,它提供了printStackTrance()等接口用于获取堆栈跟踪数据信息
Exception 以及子类是Throwable的一种形式,它指出了合理的应用程序想要捕获的条件
3.RuntimeException 是那些可能在java虚拟机正常运行期间抛出的异常的超类 编译器不会检查运行时异常 如果代码产生RuntimeException,则需要通过修改代码避免。
Error:和Exception一样,也是Throwable的子类,它用于指示合理程序不应该出现试图捕获的严重问题,编译器也不会检查
java异常分为两类:
1,被检查的异常(Checked Exception) Exception中除了运行时异常就都称为编译异常
2.运行时异常(RuntimeException)—RuntimeException以及其子类 3.错误(Error) 内存溢出
总结
以上所述是小编给大家介绍的java基面试础知识详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!