Java软件开发技术面试题总结二

 

常见的基础内容:
Java 的命名规范:
Java是大小写敏感的,这就意味着标识符Hello与hello是不同的
java的变量命名规范:首字母:英文字母、$和下划线。变量名:由$、字母、数字和下划线组成。
类名:单个单词,首字母大写,多个单词,首字母都大写。
方法名、参数名、变量名:单个单词,首字母小写,多个单词,第一单词首字母小写,其他单词首字母大写。
包名:全部小写。
java的修饰符:  
    非访问控制修饰符 : final, abstract, static, synchronized
    访问控制修饰符 : default, public , protected, private
 
java语言的变量类型:【全局变量是有默认值的,int类型默认值为0,string类型默认为null,局部变量必须要进行初始化】
1、类变量:独立与方法之外的变量,用static进行修饰
2、实例变量:独立于方法之外的变量,不过没有static进行修饰
3、局部变量:类的方法中的变量,局部变量必须要进行初始化
public class Variable{
static int allClicks=0; // 类变量 ,全局变量
String str="hello world"; // 实例变量
public void method(){
int i =0; // 局部变量
}
}
java枚举:【枚举可以单独声明或者声明在类里面。方法、变量、构造函数也可以在枚举中定义。使用枚举可以减少代码中的 bug。】
class FreshJuice {
     enum FreshJuiceSize{ SMALL, MEDIUM , LARGE } 
     FreshJuiceSize size; 
public class FreshJuiceTest { 
    public static void main(String []args){ 
        FreshJuice juice = new FreshJuice(); 
        juice.size = FreshJuice.FreshJuiceSize.MEDIUM ; 
    } 
}
Java的do,while循环【首先就是会进行do里面的内容的执行,然后在判断while的内容是不是符合规定,如果里面的条件是符合规定的,再次执行do里面的内容,直到不满足条件】
public class StringBase {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int a=sc.nextInt();
        do {
            System.out.println(a);
            a++;
        }
        while (a<=10);
        System.out.println("结束");
    }
}
while循环就是判断是不是满足while里面的内容,如果满足的执行while里面的循环体,如果不满足,就直接跳出
public class StringBase {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int a=sc.nextInt();
        while (a<=10){
            System.out.println(a);
            a++;
        }
        System.out.println("结束");
    }
}
instanceof(实例)【instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为:】
boolean result = obj instanceof Class
其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。
 
throw和throws的区别
1、throws出现在方法函数头;而throw出现在函数体。
2、throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常。
3、两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
 
Java虚拟机
java虚拟机实际上只是一层接口,一层Java程序和操作系统通讯的接口。java文件编译生成class文件,
而java虚拟机就是这些class文件能够在上面运行的一个平台,你把class文件看成一个软件,java虚拟机就是这个软件可以运行的操作系统。
解释运行字节码程序(Java程序编译后产生)、消除平台差异性
使用Java虚拟机是实现这一特点的关键 一般的高级语言如果要在不同的平台上运行 至少需要编译成不同的目标代码 而引入Java语言虚拟机后 Java语言在不同平台上运行时不需要重新编译 Java语言使用模式Java虚拟机屏蔽了与具体平台相关的信息 使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码)就可以在多种平台上不加修改地运行 Java虚拟机在执行字节码时 把字节码解释成具体平台上的机器指令执行
 
Java应用的特点
1、一个源文件中只能有一个public修饰的类,其他类个数不限。
2、一个源文件有n个类时,编译结果的class文件就有n个。
3、源文件的名字必须和public修饰的类名相同
4、java语言中单词拼写大小写严格区分。
5、main方法入口
6、每一句以分号(;)结束
 
 
Java类中方法的调用【在一个源文件中,只能有一个public修饰的类,并且在类中定义的 static方法,可以直接进行方法名的调用】
class test{
    public static void test4(){
        System.out.println("test4");
    }
    public void test1(){
        test4();//可以直接进行调用的
        System.out.println("test1");
    }
}
public class StringBase {
    public void test2(){
        System.out.println("test2");
    }
    public static void test3(){
        System.out.println("test3");
    }
    public static void main(String[] args) {
        test.test4();//静态方法可以直接用类名.方法名直接调用
       test test=new test();
       test.test1();//要定义类的对象,对象调用类里面的方法
       StringBase sb=new StringBase();
       sb.test2();
       test3();//可以直接进行调用
    }
}
 
 
执行结果:
test4
test4
test1
test2
test3
 
 
Java的单引号和双引号的区别:
单引号引的数据 是char类型的——》单引号只能引一个字符(表示单个字符)
双引号引的数据 是String类型的——》而双引号可以引0个及其以上(引用字符串)
首先单引号引起来的都是单字符例如:char a='a';这样是可以使用的,但是如果String a=‘a’ 和String a='aa' 这样就是会报错的,超过一位的字符就要使用String
 
三目运算符:X ? Y : Z
min=(a<b)?a:b;这样,在a<b的情况下,min=a,否则min=b
 
程序的流程控制
结构化程序的三种结构:顺序、选择(分支)、循环
 
switch的选择分支结构:
switch (a){
    case 2:
        System.out.println(3);
        break;//加上break会跳出本次的switch选择结构
    case 3:
        System.out.println(3);
}
 
 
递归的特征:
函数有返回值类型、函数有参数、函数中有跳出循环的控制语句、自己调用自己
 
java的静态(static)
在静态的情况下:可以使用  类名.方法名 类名.属性名 这样的方式直接进行调用对应的属性或者是方法名.
也可以进行对象的创建,然后用对象进行属性或者是方法名的调用;
 
public class StringBase {
    static int a;//全局变量,类变量,初始默认值是0
    public static void test3(){
        String  test="test";
        System.out.println("test3");
    }
    public static void main(String[] args) {
        System.out.println(StringBase.a);
        StringBase.test3();
        StringBase sb =new StringBase();
        System.out.println(sb.a);
        sb.test3();
    }
}
在非静态的情况下,只能使用对象进行相应的调用
 
java中的this的使用
【在类的构造器中使用,并且this后面调用的全是本类中的资源(变量,方法{普通函数:this.test1();有参构造this(int n);无参构造this();})】
1、在有参构造中的使用,构造函数的默认类型是public
class Person{
    private String name;
    private int age;
    public Person(String name,int age) {
        this.name = name;   //this.name明确表示调用类中name属性就近原则,不再使用
        this.age = age;
    }
    public void getpersonInfo(){
        System.out.println("姓名:"+name+",年龄:"+age);
    }
}
public class ThisTest {
    public static void main(String[] args){
        Person per=new Person("张二",25);
        per.getpersonInfo();
    }
}
 
执行结果:姓名:张二,年龄:25
2、可以调用类中的方法
public class ThisTest {
    private String name;
    private int age;
    public ThisTest(String name,int age) {
        this.name = name;
        this.age = age;//this.age表示本类属性
        this.print("#############");//调用普通方法
    }
    public  void print(String n){
        System.out.println(n);
    }
    public String getpersonInfo(){
        return "姓名:"+name+",年龄:"+age;
    }
    public static void main(String[] args){
        ThisTest per=new ThisTest("张三",30);
        System.out.print (per.getpersonInfo());
    }
}
执行结果:
#############
姓名:张三,年龄:30
3、调用类中的构造方法(有参构造方法/无参构造方法)
public class ThisTest {
    private String name;
    private int age;
    public ThisTest() {
        System.out.println("***产生一个新的person对象***");
    }
    public ThisTest(String name) {
        this();//调用本类中无参构造
        this.name=name;
    }
    public ThisTest(String name,int age) {
        this(name);//调用本类有参构造
        this.age=age;
    }
    public String getpersonInfo(){
        return "姓名:"+name+",年龄:"+age;
    }
    public static void main(String[] args){
        ThisTest per1=new ThisTest();
        System.out.println (per1.getpersonInfo());
        ThisTest per2=new ThisTest("张二");
        System.out.println (per2.getpersonInfo());
        ThisTest per3=new ThisTest("张三",30);
        System.out.println (per3.getpersonInfo());
    }
}
执行结果:
***产生一个新的person对象***
姓名:null,年龄:0
***产生一个新的person对象***
姓名:张二,年龄:0
***产生一个新的person对象***
姓名:张三,年龄:30
 
java的super的使用
super是调用父类里面的资源(变量和类,this是调用本类中的资源和方法)
java初始化顺序。初始化子类必先初始化父类。子类的构造方法会隐式去调用 父类无参的构造方法(不会在代码中显示)。但如果父类没有无参的构造方法,就必须在子类构造方法第一行显示调用父类的有参构造方法。否则编译失败
1、子类继承父类的时候,会自动调用父类的无参构造器
class Person{
    Person(){//无参构造器
        System.out.println("person");
    }
}
public class ThisTest extends Person{
    ThisTest(){
        System.out.println("ThisTest");
    }
    public static void main(String[] args){
        ThisTest tt=new ThisTest();
    }
}
执行结果:
person
ThisTest
2、子类调用父类的方法和属性【子类没有进行初始化,则父类的初始化也不会有要求,只有在子类进行构造器初始化的时候,才会涉及到父类里面的初始化】
class Country {
    String name;
    void value() {
        System.out.println("china");
        name = "China";
    }
}
class ThisTest extends Country {
    String name;
    void value() {
        name = "Hefei";
        super.value();//不调用此方法时,super.name返回的是父类的成员变量的值null
        System.out.println(name);
        System.out.println(super.name);
    }
    public static void main(String[] args) {
        ThisTest c=new ThisTest();
        c.value();
    }
}
执行结果:
china
Hefei
China
3、子类调用父类中的构造方法(在子类中不写super的情况下,默认会调用父类的无参构造器,如果super中传入参数的话,会调用父类中对应的有参构造)
class Person {
    public static void prt(String s) {
        System.out.println(s);
    }
    Person() {
        prt("A Person.");
    }
    Person(String name) {
        prt("A person name is:" + name);
    }
}
public class ThisTest extends Person {
    ThisTest() {
        super(); // 调用父类构造函数(1)
        prt("A chinese.");// (4)
    }
    ThisTest(String name) {
        super(name);// 调用父类具有相同形参的构造函数(2)
        prt("his name is:" + name);
    }
    ThisTest(String name, int age) {
        this(name);// 调用当前具有相同形参的构造函数(3)
        prt("his age is:" + age);
    }
    public static void main(String[] args) {
        ThisTest cn = new ThisTest();
        cn = new ThisTest("kevin");
        cn = new ThisTest("kevin", 22);
    }
}
执行结果:
A Person.
A chinese.
A person name is:kevin
his name is:kevin
A person name is:kevin
his name is:kevin
his age is:22
 
java的final关键字
1、final可以修饰全局变量,并且在进行变量创建的时候,必须要进行初始化;也可以修局部变量,但是也必须要进行初始化赋值
static final int a=0;
2、final修饰方法,对final修饰的方法,用子类继承父类时候,是不可以进行重写的
class Animal {
    public final  void move() {//用final进行修饰方法时候,子类是无法进行重写父类方法的
            System.out.println("动物可以动");
    }
}
class Dog extends Animal {
    public void move() {
        System.out.println("狗可以跑和走");
    }
}
public class ThisTest {
    public static void main(String[] args) {
        Animal a = new Animal(); // Animal 对象
        Animal b = new Dog(); // Dog 对象,由父类创建的子类对象
        a.move();// 执行 Animal 类的方法
        b.move();//执行 Dog 类的方法
    }
}
执行结果:报错:
Error:(9, 17) java: com.zch.springboot_mybatis.Dog中的move()无法覆盖com.zch.springboot_mybatis.Animal中的move()
  被覆盖的方法为final
3、final修饰类,则此类无法在进行继承
final class Animal {
    public   void move() {//用final进行修饰方法时候,子类是无法进行重写父类方法的
            System.out.println("动物可以动");
    }
}
class Dog extends Animal {
    public void move() {
        System.out.println("狗可以跑和走");
    }
}
public class ThisTest {
    public static void main(String[] args) {
        Animal a = new Animal(); // Animal 对象
        Animal b = new Dog(); // Dog 对象,由父类创建的子类对象
        a.move();// 执行 Animal 类的方法
        b.move();//执行 Dog 类的方法
    }
}
执行结果:
报错:Error:(8, 19) java: 无法从最终com.zch.springboot_mybatis.Animal进行继承
 
java面向对象的三大特性
1、封装(可以提高代码的的安全性):
    将属性进行私有化,并且提供对外界的接口(get/set方法)
    用private进行修饰属性和方法,并且只能在本类中进行使用
2、继承(可以提高代码的复用性,减少重复代码)
    子类可以继承父类的非私有的属性和方法,但是不可以继承父类的构造方法以及私有属性和方法
    子类在继承父类的元素的时候,也可以进行修改(重写)
    一个子类只能继承一个父类,必须是单继承
    子类可以通过使用super进行参数的传递,进行父类的有参构造器的初始化
3、多态性:
    运行时多态性:重写(子类继承父类的方法进行重写,但是子类方法的访问类型要大于父类的访问类型)
    编译时多态性:重载(重载就是同名方法的不同参数)
 
java的抽象类(用abstract进行修饰的类)
1、如果一个类里面有抽象方法,那么这个类必须定义为抽象的;
2、抽象类是不能进行创建对象的,因为抽象类不能进行实例化
3、继承抽象类,使用的关键字是extends
Java的接口(interface)
1、实现接口用implements关键字
2、接口中只有全局变量和抽象方法
3、接口在实现的时候,同时去继承,extends在implements前面
Java排序算法:
1、冒泡排序
public class MaoPao {
    public static void main(String []args ){
        int a[]={1,3,4,5,2,7,6,10,9,8};
        for(int i=0;i<a.length-1;i++){//控制外循环的次数
            for(int j=0;j<a.length-1-i;j++){//控制内循环次数,比外循环少一次,与下一个比较
                if(a[j]>a[j+1]){
                    int temp=a[j];
                    a[j]=a[j+1];
                    a[j+1]=temp;
                }
            }
        }
    }
}
2、选择排序
public class MaoPao {
    public static void main(String []args ){
        int a[]={1,3,4,5,2,7,6,10,9,8};
        for (int i = 0; i < a.length-1; i++) {
            int k=i;
            for (int j = i; j < a.length-1; j++) {
                if (a[k]>a[j+1]) {
                    k=j+1;
                }
            }
            if(i!=k){
                int temp=a[i];
                a[i]=a[k];
                a[k]=temp;
            }
        }
        for (int i=0; i<a.length;i++){
            System.out.println(a[i]);
        }
    }
}
Java的StringBuffer用法
String 长度不可变
StringBuffer 长度可变 线程安全 速度慢
StringBuilder 长度可变 线程不安全 速度快
StringBuffer sb=new StringBuffer("a");
System.out.println(sb);
sb.append("b");//追加
System.out.println(sb);
sb.insert(2,"cde");//在指定位置进行插入
System.out.println(sb);
sb.delete(2,3);//在指定位置进行删除
System.out.println(sb);
sb.reverse();//反向逆转
System.out.println(sb);
执行结果:
a
ab
abcde
abde
edba
Java的线程与进程
1、多线程,从宏观的角度看就是同时执行多个进程,在微观的角度看待就是同一时间只能执行一个线程
2、进程是应用程序,线程就是一条执行路径
3、在一个进程中,至少有一个线程
4、开启一个线程,可以继承Thread的类,重写run方法,然后创建类对象,然后对象.start();
class ThreadTest extends Thread{
    //继承Thread类,重写run()方法
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"执行Run中");
        System.out.println(Thread.currentThread().getName()+"执行完毕");
    }
}
public class ExtendThread{
    public static void main(String[] args) {
        new ThreadTest().start();
        new ThreadTest().start();
        new ThreadTest().start();
        new ThreadTest().start();
        new ThreadTest().start();
    }
}
还可以通过实现 Runnable接口,重写run方法,创建类对象,然后new Thread(类对象).start 然后通过start来启动多线程
class ThreadTest implements Runnable{
    //实现Runnable接口,实现run()方法
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"执行Run中");
        System.out.println(Thread.currentThread().getName()+"执行完毕");
    }
}
public class ExtendThread{
    public static void main(String[] args) {
        ThreadTest runnable = new ThreadTest();
        new Thread(runnable).start();
        new Thread(runnable).start();
        new Thread(runnable).start();
        new Thread(runnable).start();
        new Thread(runnable).start();
    }
}
首先run是没有开辟新的栈空间,没有新线程,都是主程序在执行
start开辟了新的栈空间,在新的栈空间里面启动run()方法
tcp和udp
1、tcp:面向连接,数据传输是可靠的,传输效率 偏低,传输数据的大小没有限制
2、udp:面向无连接,数据安全不可靠,执行效率比较高,数据的大小不超过64kb
【tcp和udp只是传输协议,只是设定了规范,真正起到传输作用的是数据ip协议】
【ip协议:将数据从源传递到目的地,ipv4是32位,ipv6是128位】
 
Java的反射机制
反射就是将Java类中的信息进行拆分,包括属性、方法、构造方法,并且可以进行调用
优点:
    1、提高了Java程序的灵活性和拓展性,降低了耦合性,提高了自适应的能力
    2、允许程序创建和控制任何类的对象,无需提前编码目标类
 
get和post的区别:
GET产生一个TCP数据包;POST产生两个TCP数据包。
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
GET请求会被浏览器主动cache,而POST不会
在类中不能直接进行运算,要写在方法代码块{}或者静态代码块中static{}中
public abstract class MaoPao {
    public int constInt = 5;
    consInt=constInt+5;
    private static void testMethod(){
        System.out.println("testMethod");
    }
    public static void main(String[] args) {
        ((MaoPao)null).testMethod();
    }
}
这样在里面consInt=constInt+5;是会报错的
Java在多线程下的sleep和 wait()
共同点 : 
1. 他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。 
2. wait()和sleep()都可以通过interrupt()方法 打断线程的暂停状态 ,从而使线程立刻抛出InterruptedException。 
如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep/join,则线程B会立刻抛出InterruptedException,在catch() {} 中直接return即可安全地结束线程。 
需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用 interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到 wait()/sleep()/join()后,就会立刻抛出InterruptedException 。 
不同点 : 
1.每个对象都有一个锁来控制同步访问。Synchronized关键字可以和对象的锁交互,来实现线程的同步。 
sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。 
2.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用 
3.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常 
4.sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
5.wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
 
 
原文地址:https://www.cnblogs.com/zhaochunhui/p/11629564.html