参考Java程序员面试笔试宝典:
目录
1.Java和C/C++异同
1) java经编译器编译成字节码,再由JVM虚拟机执行,而C/C++直接经编译生成二进制代码,java速度较C/C++慢,但能够跨平台执行。
2)java面向对象,所有代码在类中实现,不存在全局变量和全局函数,而C/C++兼具面向过程和面向对象,可定义全局变量和全局函数。
3)java没有指针,防止误操指针引起的系统问题。
4)java不支持多重继承,但引入接口概念,可同时实现多个接口。(接口的多态性)
5)C++需要手动管理内存,java实现了垃圾回收器自动回收内存。finalize()方法
6)C++支持运算符重载,java不支持;C++支持预处理,java提供的import机制类似;
C++支持默认函数参数,java不支持默认函数参数;C/C++支持goto语句,java中goto是保留关键字;
7) C/C++支持自动强制类型转换,java不支持,必须开发人员显示强制转换。
8)C/C++结构和联合的所有成员均为公有,存在安全性问题,java不包含,所有内容封装在类。
9)java平台无关性,每种数据类型分配固定长度,C/C++不同平台分配不同字节数。
10)java提供对注释文档的内建支持;包含一些标准库(JDBC、RMI)
2.为什么需要main函数
java程序的入口方法,JVM运行程序,首先查找main()方法。
注意:必须public和static修饰,顺序可颠倒,返回值void,可用final和synchronized修饰,不能adstract修饰
3.如何在main方法前输出hello world
java语言中,静态块在类被加载时就会被调用
public class Test {
static {
System.out.println("hello world");
}
public static void main(String[] args) {
System.out.println("main方法");
}
}
结果:
hello world
main方法
4.java程序初始化顺序
父类静态变量
父类静态代码块
子类静态变量
子类静态代码块
父类非静态变量
父类非静态代码块
父类构造函数
子类非静态变量
子类非静态代码块
子类构造函数
三个原则:静态对象>非静态对象 ; 父类>子类 ; 按照成员变量的定义顺序初始化。
5.java作用域
java三种变量类型:成员变量、静态变量、局部变量
public:对所有类或对象可见
private:只有当前类有访问权限
protected:同一包下的其他类可见,不同包的子类可见
default:同一包下其他类可见,其他包下子类不可见
6.何为构造函数
特殊的函数,用来在对象实例化时初始化对象的成员变量。
特点:构造函数与类名相同,不能有返回值;可有多个构造函数,默认无参构造函数,若提供有参构造函数,则不会提供无参构造函数;伴随new操作一起调用,系统调用,只运行一次;不能被继承,能够重载;子类可通过super关键字显示调用父类构造函数。
若父类没有无参构造函数,子类必须显式调用父类的有参构造函数。
7.为什么java中有些接口没有方法
java不支持多重继承,即一个类只能有一个父类,为克服单继承的缺点,java引入接口概念。
接口是抽象方法定义的集合,也可定义一些常量值,是一种特殊的抽象类。
接口只有方法的定义,没有方法的实现。
从java8开始,接口可以默认方法和静态方法。
接口中所有方法都是抽象,成员的作用域都是public,常量值默认public static final修饰。
没有方法的接口又被称作标识接口,仅仅充当一个标识的作用,类似于汽车的标志图标。
8.java中的clone方法有什么用
java取消了指针,很多人忽略了对象和引用的区别。
java处理基本数据类型都是按值传递(输入参数的复制),其他都是按引用传递,包括函数调用和“=”赋值。
实际编程时,已有对象A,需创建一个与A具有相同的状态对象B,且B的改变不会影响A。简单的赋值操作无法完成,因此java提供了简单有效的clone()方法来满足需求。
适用clone()方法的步骤:
1)继承Cloneable接口(Cloneable中没有任何接口方法)
2)在类中重写clone()方法
3)在clone()方法中调用super.clone()
4)把浅复制的引用指向原型对象新的克隆体。
class Obj implements Cloneable{
private int anInt=0;
public int getAnInt() {
return anInt;
}
public void setAnInt(int anInt) {
this.anInt = anInt;
}
public void changeInt(){
this.anInt=1;
}
public Object clone(){
Object o=null;
try{
o=(Obj)super.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return o;
}
}
public class Test {
public static void main(String[] args) {
Obj a=new Obj();
Obj b =(Obj)a.clone();
b.changeInt();
System.out.println("a:"+((Obj) a).getAnInt());
System.out.println("b:"+b.getAnInt());
}
}
结果:
a:0
b:1
当类中只存在一些基本数据类型,上述方法就可以了,当类中包含对象,需要使用深复制:在对对象调用clone()方法后,对非基本类型的属性也调用clone()方法完成深复制。
import java.util.Date;
class Obj implements Cloneable{
private Date date =new Date();
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public void changeDate(){
this.date.setMonth(6);
}
public Object clone(){
Obj o=null;
try{
o=(Obj)super.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
o.date=(Date)this.getDate().clone();
return o;
}
}
public class Test {
public static void main(String[] args) {
Obj a=new Obj();
Obj b=(Obj) a.clone();
b.changeDate();
System.out.println("a:" +a.getDate());
System.out.println("b:"+b.getDate());
}
}
结果:
a:Wed Mar 11 16:50:54 CST 2020 b:Sat Jul 11 16:50:54 CST 2020
总结:若类中只有基本数据类型,使用浅复制,返回super.clone();若存在非基本类型(对象),使用深复制。
Object o=super.clone();//浅复制
对每一对象attr执行:o.attr=this.getAttr().clone();
最后返回o
9.什么是反射机制
反射机制允许程序在运行时进行自我检查,同时允许对其内部成员进行操作,实现在运行时对类进行装载。
反射机制提供的主要功能:1)得到一个对象所属的类;
2)获取一个类的所有成员变量和方法;
3)在运行时创建对象,在运行时调用对象的方法
在运行时动态创建类的对象:
package day0311;
class Base{
public void p(){
System.out.println("Base");
}
}
class Sub extends Base{
public void p(){
System.out.println("Sub");
}
}
public class Test {
public static void main(String[] args) {
try{
Class c=Sub.class;
Base b=(Base) c.newInstance();
b.p();
}catch (Exception e){
e.printStackTrace();
}
}
}
结果:
Sub
如何获取Class类:
1)Class.forName(“类的路径”)
2)类型.Class
3)实例.getClass()
java创建对象有几种方式:
1)通过new对象
2)通过反射机制
3)通过clone()方法
4)通过反序列化的方式
10.package有什么作用
1)提供多层命名空间,解决命名冲突,使得处于不同包下的类可以存在相同的名字;
2)对类按功能进行分类,使项目组织更加清晰。
11.如何实现类似于C语言中函数指针的功能
C语言中函数指针最重要的功能是实现函数回调,一般用于截获消息、获取系统信息、处理异步事件。
函数指针一般作为函数参数来使用,开发人员可根据需求来传递自定义的函数实现指定功能。
java中没有指针,利用接口和类可实现同样的效果——先定义一个接口,在接口中声明要调用的方法,接着实现这个接口,最后把实现类对象作为参数传递给调用程序,调用程序通过这个参数来调用指定的函数。
interface IntCompare{
public int cmp(int a,int b);
}
class Com1 implements IntCompare{
public int cmp(int a,int b){
if(a>b) return 1;
else if(a<b) return -1;
else return 0;
}
}
class Com2 implements IntCompare{
public int cmp(int a,int b){
if(a>b) return -1;
else if(a<b) return 1;
else return 0;
}
}
public class Test {
public static void insertSort(int[] a,IntCompare cmp){
if(a!=null){
for(int i=1;i<a.length;i++){
int temp=a[i],j=i;
if(cmp.cmp(a[j-1],temp)==1){
while(j>=1&&cmp.cmp(a[j-1],temp)==1){
a[j]=a[j-1];
j--;
}
}
a[j]=temp;
}
}
}
public static void main(String[] args) {
int[] array1={7,3,19,40,4,7,1};
insertSort(array1,new Com1());
System.out.print("升序排列: ");
for (int i = 0; i < array1.length; i++) {
System.out.println(array1[i]+" ");
}
System.out.println();
int[] array2={7,3,19,40,4,7,1};
insertSort(array2,new Com2());
System.out.print("降序排列: ");
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i]+" ");
}
}
}
结果:
升序排列: 1 3 4 7 7 19 40
降序排列: 40 19 7 7 4 3 1