Java面试基础及语法

1.Java跨平台原理

C/C++语言都是直接编译成针对特定平台的机器码。如果要跨平台,需要使用相应的编译器重新编译。

Java源程序(.java)要先编译成字节码文件(.class),然后字节码文件再通过Java虚拟机(JVM)解析成机器码运行。

字节码文件不面向任何具体平台,只面向虚拟机。

Java虚拟机是可运行Java字节码文件的虚拟计算机。不同平台的虚拟机是不同的,但都提供了对应的接口。

Java语言具有一次编译,到处运行的特点,就是编译后的字节码文件可以跨平台运行,前提是该平台具有相应的Java虚拟机。

但是Java的跨平台原理决定了它的性能要比C/C++要低。(因为C是直接执行编码,Java是先将字节码文件解释成机器码再执行)

2.Java的安全性

语言层次的安全性:

Java用引用来代替了强大但又危险的指针。由于指针可进行移动运算,指针可以随便指向一个内存区域,而不管这个区域是否可用,这样做是危险的,因为这个内存地址可能存储着重要数据或者其他程序运行所占用的。

垃圾回收机制:

不需要人为控制内存回收,由于垃圾回收器在后台自动回收不再使用的内存。避免程序忘记及时回收,导致内存泄漏。避免程序错误回收核心类库的内存,导致系统崩溃。

异常处理机制:

依赖于try、catch、finally、throw、throws五个关键字

强制类型转换:

只有满足前置转换规则的情况下才能强转成功。

底层安全:

在字节码的传输过程中使用了公开密钥加密机制(PKC)。

在运行环境提供了四级安全性保障机制:

字节码校验器-类装载器-运行时内存分布-文件访问限制

3.Java三大版本

标准版(J2SE)、企业版(J2EE)、微缩版(J2ME):

J2SE包含于J2EE中,J2ME包含了J2SE的核心类,但添加了一些专有类应用场合,API的覆盖范围各不相同

4.JVM?JDK?JRE?

JVM是Java Virtual MachineJava虚拟机)的缩写,它是整个Java实现跨平台的最核心的部分,所有的java程序会首

先被编译为.class的类文件,这种类文件可以在虚拟机上执行,也就是说class并不直接与机器的操作系统相对应,而

是经过虚拟机间接与操作系统交互,由虚拟机将程序解释给本地系统执行。JVMJava平台的基础,和实际的机器一

样,它也有自己的指令集,并且在运行时操作不同的内存区域。 JVM通过抽象操作系统和CPU结构,提供了一种与平

台无关的代码执行方法,即与特殊的实现方法、主机硬件、主机操作系统无关。JVM的主要工作是解释自己的指令集

(即字节码)到CPU的指令集或对应的系统调用,保护用户免被恶意程序骚扰。 JVM对上层的Java源文件是不关心

的,它关注的只是由源文件生成的类文件(.class文件)。

JREjava runtime environmentjava运行环境)的缩写。光有JVM还不能让class文件执行,因为在解释class的时候

JVM需要调用解释所需要的类库lib。在JDK的安装目录里你可以找到jre目录,里面有两个文件夹binlib,在这里可以

认为bin里的就是jvmlib中则是jvm工作所需要的类库,而jvmlib和起来就称为jre。所以,在你写完java程序编译

.class之后,你可以把这个.class文件和jre一起打包发给朋友,这样你的朋友就可以运行你写程序了(jre里有运

.classjava.exe)。JRESun公司发布的一个更大的系统,它里面就有一个JVMJRE就与具体的CPU结构和操作

系统有关,是运行Java程序必不可少的(除非用其他一些编译环境编译成.exe可执行文件……),JRE的地位就象一台

PC机一样,我们写好的Win32应用程序需要操作系统帮我们运行,同样的,我们编写的Java程序也必须要JRE才能运

行。

JDKjava development kitjava开发工具包)的缩写。每个学java的人都会先在机器上装一个JDK,那 让我们看一

JDK的安装目录。在目录下面有六个文件夹、一个src类库源码压缩包、和其他几个声明文件。其中,真正在运行

java时起作用的是以下四个文件夹:binincludelibjre。现在我们可以看出这样一个关系,JDK包含JRE,而JRE

包含JVM

bin: 最主要的是编译器(javac.exe)

include: javaJVM交互用的头文件

lib类库

jre: java运行环境

(注意:这里的binlib文件夹和jre里的binlib是不同的)

总的来说JDK是用于java程序的开发,jre则是只能运行class而没有编译的功能。eclipseidea等其他IDE有自己的编

译器而不是用JDK bin目录中自带的,所以在安装时你会发现他们只要求你选jre路径就ok了。

JDK,JRE,JVM三者关系概括如下:

jdkJAVA程序开发时用的开发工具包,其内部也有JRE运行环境JREJREJAVA程序运行时需要的运行环境,就是说

如果你光是运行JAVA程序而不是去搞开发的话,只安装JRE就能运行已经存在的JAVA程序了。JDkJRE内部都包含

JAVA虚拟机JVMJAVA虚拟机内部包含许多应用程序的类的解释器和类加载器等等。

5.八种基本数据类型

6.i++和++i的区别

共同点:

1.都是变量自增加1,都等于i=i+1

2.都仅对变量有效,不是变量会出错

3.单条语句,没有区别

不同点:

不是单条语句

 

7.&&& , ||| 的区别和联系

& && 的联系 ( 共同点 )
& && 都可以用作逻辑与运算符,但是要看使用时的具体条件来决定。
操作数 1& 操作数 2 ,操作数 1&& 操作数 2
表达式 1& 表达式 2 ,表达式 1&& 表达式 2
情况 1 当上述的操作数是 boolean 类型变量时, & &&都可以用作逻辑与运算符。
情况 2 当上述的表达式结果是 boolean 类型变量时, & && 都可以用作逻辑与运算符。表示逻辑与 (and) ,当运算符
两边的表达式的结果或操作数都为 true 时,整个运算结果才为 true ,否则,只要有一方为 false ,结果都为 false
& && 的区别 ( 不同点 )
1. & 称为逻辑与运算符, && 称为短路与运算符,也可叫逻辑与运算符。
对于 & :无论任何情况, & 两边的操作数或表达式都会参与计算。
对于 && :当 && 左边的操作数为 false 或左边表达式结果为 false 时, && 右边的操作数或表达式将不参与计算,此时最
终结果都为 false
综上所述,如果逻辑与运算的第一个操作数是 false 或第一个表达式的结果为 false 时,对于第二个操作数或表达式是
否进行运算,对最终的结果没有影响,结果肯定是 false 。推荐平时多使用 && ,因为它效率更高些。
2. & 还可以用作位运算符。当 & 两边操作数或两边表达式的结果不是 boolean 类型时, & 用于按位与运算符的操
作。
| || 的区别和联系与 & && 的区别和联系类似

 

8.基本数据类型的数据转换

分为自动转换和强制转换

自动转换规则:容量小的数据类型自动转换为容量大的数据类型,这里的容量是指类型表述的范围

强制转换规则:高变低需要强制转换

如何转换:
1 )、赋值运算符 “=” 右边的转换,先自动转换成表达式中级别最高的数据类型,再进行运算。
2 )、赋值运算符 “=” 两侧的转换,若左边级别 > 右边级别,会自动转换;若左边级别 == 右边级别,不用转换;若左
边级别 < 右边级别,需强制转换。
3 )、可以将整型常量直接赋值给 byte, short, char 等类型变量,而不需要进行强制类型转换,前提是不超出其表述范围,否则强转。

9.if和switch区别

相同之处:都是分支语句,多超过一种的情况进行判断处理

不同之处:switch更适合用于多分支情况,就是有很多种情况需要判断处理,判断条件类型单一,只有一个入口,在分支执行完

后(如果没有 break 跳出),不加判断地执行下去 ; if—elseif---else 多分枝主要适用于分支较少的分支结构,判断类
型不是单一,只要一个分支被执行后,后边的分支不再执行。
switch 为等值判断(不允许比如 >= <= ),而 if 为等值和区间都可以, if 的使用范围大。

10.whiledo-while循环的区别

while先判断后执行,第一次判断为 false , 循环体一次都不执行。
do while 先执行 后判断,最少执行 1 次。
如果 while 循环第一次判断为 true, 则两种循环没有区别。

11.breakcontinue的作用

break: 结束当前循环并退出当前循环体。 break 还可以退出 switch 语句
continue: 循环体中后续的语句不执行,但是循环没有结束,继续进行循环条件的判断( for 循环还会 i++ )。
continue 只是结束本次循环。

12.请使用递归算法计算n

阶乘亦可以递归方式定义:0!=1n!=(n-1)!×n

public class zxc {
    
    public static void main(String[] args) {
        long a = zxc.jiecheng(25);
        System.out.println(a);
        
    }
    public static int jiecheng(int num) {
        if (num == 0 || num == 1) {
            return 1;
        }else {
            return num*jiecheng(num-1);
        }
    }
}

13.递归的定义和优缺点

递归算法是一种直接或者间接调用自身算法的过程,对解决一大类问题十分有效,使算法的描述简洁而且易于理解

特点:

1.递归就是在过程或函数里调用自身

2.在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口

3.递归算法解题通常显得很简洁,但运行效率较低。

4. 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所
 
以一般不提倡用递归算法设计程序。

14.数组的特征

1.具有相同数据类型的有序集合。

2.数组会在内存中开辟一块连续的空间,每个空间相当于之前的一个变量,称为数组的元素。

元素的表示 数组名[下标或者索引]

索引从0开始

数组元素有序的,不是大小顺序,是索引的顺序

3.每个数组元素有默认值 double 0.0; boolean false; int 0

4.数组中可以存储基本数据类型,可以存储引用数据类型;但是对于一个数组而言,数组的类型是固定的,只能是一个
 
 
5.数组的长度是固定的,一经定义,不能再发生变化(数组的扩容)

15.冒泡排序

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从小到大、首字母从 A Z )错误
 
就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
 
这个算法的名字由来是因为越大的元素会经由交换慢慢 到数列的顶端(升序或降序排列),就如同碳酸饮料中二
 
氧化碳的气泡最终会上浮到顶端一样,故名 冒泡排序
 
冒泡排序算法的原理如下:
 
1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
 
2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的
数。
 
3. 针对所有的元素重复以上的步骤,除了最后一个。
 
4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

public class zxc {
    
    public static void main(String[] args) {
        int array[] = {12,31,32,15,15,1,1,31,3};
        int sort[] = zxc.sort(array);
        for (int i : sort) {
            System.out.print(i+",");
        }
        
    }
    public static int[] sort(int[] array) {
        int temp = 0;
        // 外层循环,它决定一共走几趟 //-1为了防止溢出
        for (int j = 0; j < array.length-1; j++) {
            int flag = 0;//通过符号位可以减少无谓的比较,如果已经有序了,就退出循环
            //内层循环,它决定每趟走一次
            for (int i = 0; i < array.length-j-1; i++) {
                //如果后一个小于于前一个,则换位,从小到大排序(升序)
                if (array[i+1] < array[i]) {
                    temp = array[i];
                    array[i] = array[i+1];
                     array[i+1] = temp;
                     flag = 1;
                }
            }
            if (flag == 0) {
                break;
            }
        }
        return array;
    }
}

16.可变参数的作用和特点

https://www.cnblogs.com/uptownBoy/articles/1698335.html

17.类和对象的关系

类是对象的抽象,而对象是类的具体实例。 类是抽象的,不占用内存,而对象是具体的,占用存储空间。 类是用于创建对象的蓝图,类就
 
是一个带方法和变量的特定类型 。类和对象好比图纸和实物的关系,模具和铸件的关系

18.面向过程和面向对象的区别

都是软件开发思想,先有过程再有对象,在大型项目中,针对面向过程的不足推出了面向对象开发思

想。
比喻 :
面向过程是蛋炒饭,面向对象是盖浇饭。盖浇饭的好处就是 ”“ 分离,从而提高了制作盖浇饭的灵活性。饭不满
 
意就换饭,菜不满意换菜。用软件工程的专业术语就是 可维护性 比较好, 的耦合度比较低。蛋炒饭就不
 
行了 , 如果不满意就要丢掉重做 ;
 
区别 :
编程思路不同: 面向过程以实现功能的函数开发为主,而面向对象要首先抽象出类、属性及其方法,然后通过实例
 
化类、执行方法来完成功能。
 
封装性: 都具有封装性,但是面向过程是封装的是功能,而面向对象封装的是数据和功能。
 
面向对象具有继承性和多态性,而面向过程没有继承性和多态性,所以面向对象优势是明显
 

18.方法重载和方法重写(覆盖)的区别

19.thissuper关键字的作用

this是对象内部指代自身的引用,同时也是解决成员变量和局部变量同名问题;

this可以调用成员变量,不能调用局部变量;

this 也可以调用成员方法,但是在普通方法中可以省略 this ,在构造方法中不允许省略,必须是构造方法的第
一条语句。
 
而且在静态方法当中不允许出现 this 关键字。
 
super代表对当前对象的直接父类对象的引用,super可以调用直接父类的成员变量(除私有private成员);
 
super可以直接调用父类的成员变量(除private成员);
 
super可以调用父类的构造方法,只限构造方法中使用,且必须是第一条语句。

 

20.static关键字的作用

static 可以修饰变量、方法、代码块和内部类
static 属性属于这个类所有,即由该类创建的所有对象共享同一个 static 属性。可以对象创建后通过对象名 . 属性名和
类名 . 属性名两种方式来访问。也可以在没有创建任何对象之前通过类名 . 属性名的方式来访问。
.static 变量和非 static 变量的区别 ( 都是成员变量,不是局部变量 )
 
1. 在内存中份数不同
不管有多少个对象, static 变量只有 1 份。对于每个对象,实例变量都会有单独的一份
static 变量是属于整个类的,也称为类变量。而非静态变量是属于对象的,也称为实例变量
 
2. 在内存中存放的位置不同
静态变量存在方法区中, 实例变量存在堆内存中 *
 
 
3. 访问的方式不同
实例变量: 对象名 . 变量名 stu1.name=" 小明明 ";
静态变量: * 对象名 . 变量名 stu1.schoolName=" 西二旗小学 ";* 不推荐如此使用
类名 . 变量名 Student.schoolName=" 东三旗小学 "; 推荐使用
 
4. 在内存中分配空间的时间不同
实例变量 创建对象的时候才分配了空间。
 
静态变量:第一次使用类的时候
Student.schoolName=" 东三旗小学 "; 或者 Student stu1 = new Student(" 小明 "," ",20,98);
static 方法也可以通过对象名 . 方法名和类名 . 方法名两种方式来访问
 
static 代码块:当类被第一次使用时(可能是调用 static 属性和方法,或者创建其对象)执行静态代码块,且只被执行
一次,主要作用是实现 static 属性的初始化。
 
static内部类: 属于整个外部类,而不是属于外部类的每个对象。不能访问外部类的非静态成员(变量或者方法),
可以访问外部类的静态成员

21.finalabstract关键字的作用

fifinal abstract 是功能相反的两个关键字,可以对比记忆
 
abstract 可以用来修饰类和方法,不能用来修饰属性和构造方法;使用 abstract 修饰的类是抽象类,需要被继承,使
 
abstract 修饰的方法是抽象方法,需要子类被重写。
 
fifinal 可以用来修饰类、方法和属性,不能修饰构造方法。使用 fifinal 修饰的类不能被继承,使用 fifinal 修饰的方法不能被
 
重写,使用 fifinal 修饰的变量的值不能被修改,所以就成了常量。
 

22.java.lang.Object类的六个常用方法

(1)public boolean equals (java.lang.Object) 比较对象的地址值是否相等,如果子类重写,则比较对象的内容是否相
等;
(2)public native int hashCode() 获取哈希码
(3)public java.lang.String toString () 把数据转变成字符串
(4)public fifinal native java.lang.Class getClass () 获取类结构信息
(5)public fifinal void wait () throws java.lang.InterruptedException 多线程中等待功能
(6)public fifinal native void notify () 多线程中唤醒功能
 

23.权限修饰符的区别

类的访问权限只有两种 :
 
public 公共的 可被同一项目中所有的类访问。 ( 必须与文件名同名 )
 
default 默认的 可被同一个包中的类访问。
 
成员 ( 成员变量或成员方法 ) 访问权限共有四种:
 
public 公共的 可以被项目中所有的类访问。 ( 项目可见性 )
 
protected 受保护的 可以被这个类本身访问 ; 同一个包中的所有其他的类访问 ; 被它的子类 ( 同一个包以及不同包 中的子类) 访问。 ( 子类可见性 )
 
default 默认的被这个类本身访问 ; 被同一个包中的类访问。 ( 包可见性 )
 
private 私有的 只能被这个类本身访问。 ( 类可见性)

 

24.==equals的区别和联系

“==” 是关系运算符, equals() 是方法,同时他们的结果都返回布尔值;
 
“==” 使用情况如下:
 
a) 基本类型,比较的是值
 
b) 引用类型,比较的是地址
 
c) 不能比较没有父子关系的两个对象
 
equals() 方法使用如下:
 
a) 系统类一般已经覆盖了 equals() ,比较的是内容。
 
b) 用户自定义类如果没有覆盖 equals() ,将调用父类的 equals (比如是 Object ),而 Object equals 的比较是地址 (return (this == obj);
 
c) 用户自定义类需要覆盖父类的 equals()
 
注意: Object == equals 比较的都是地址,作用相同

 

25.谈谈Java的多态

多态性是 OOP 中的一个重要特性,主要是用来实现动态联编的,换句话说,就是程序的最终状态只有在执行过程中 才被决定而非在编译期
 
间就决定了。这对于大型系统来说能提高系统的灵活性和扩展性。
 
多态可以让我们不用关心某个对象到底是什么具体类型,就可以使用该对象的某些方法,从而实现更加灵活的编程, 提高系统的可扩展性。
 
实现多态的三个条件(前提条件,向上转型、向下转型)
 
1 、继承的存在;(继承是多态的基础,没有继承就没有多态)
 
2 、子类重写父类的方法。(多态下会调用子类重写后的方法)
 
3 、父类引用变量指向子类对象。(涉及子类到父类的类型转换)
 
向上转型 Animal a = new Cat();
 
将一个父类的引用指向一个子类对象,称为向上转型,自动进行类型转换。此时通过父类引用变量调用的方法是子类
 
覆盖或继承父类的方法,而不是父类的方法 , 此时通过父类引用变量无法调用子类特有的方法 .
 
向下转型 Cat a2 = (Cat)a;
 
将一个指向子类对象的引用赋给一个子类的引用,成为向下转型,此时必须进行强制类型转换。向下转型必须转换为
 

父类引用指向的真实子类类型,否则将出现ClassCastException,不是任意的强制转换.

向下转型时可以结合使用 instanceof 运算符进行强制类型转换,比如出现转换异常 --ClassCastException. 比如:本来
 
是狗,我把它转成猫。就会报这个异常。
 

26. 简述Java的垃圾回收机制

传统的 C/C++ 语言,需要程序员负责回收已经分配内存。
 
显式回收垃圾的缺点:
 
1 )程序忘记及时回收,从而导致内存泄露,降低系统性能。
 
2 )程序错误回收程序核心类库的内存,导致系统崩溃。
 
Java 语言不需要程序员直接控制内存回收,是由 JRE 在后台自动回收不再使用的内存,称为垃圾回收机制,简称 GC
 
1 )可以提高编程效率。
 
2 )保护程序的完整性。
 
3 )其开销影响性能。 Java 虚拟机必须跟踪程序中有用的对象,确定哪些是无用的。
 
垃圾回收机制的特点 :
 
1 )垃圾回收机制回收 JVM 堆内存里的对象空间 , 不负责回收栈内存数据。
 
2 )对其他物理连接,比如数据库连接、输入流输出流、 Socket 连接无能为力。
 
3 )垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行。
 
4 )可以将对象的引用变量设置为 null ,暗示垃圾回收机制可以回收该对象。
 
现在的 JVM 有多种垃圾回收实现算法,表现各异。
 
垃圾回收机制回收任何对象之前,总会先调用它的 fifinalize 方法(如果覆盖该方法,让一个新的引用变量重新引用该 对象,则会重新激活对象)。
 
程序员可以通过 System.gc() 或者 Runtime.getRuntime().gc() 来通知系统进行垃圾回收,会有一些效果,但是系统是 否进行垃圾回收依然不确定。
 
永远不要主动调用某个对象的 fifinalize 方法,应该交给垃圾回收机制调用。

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值