• 【面试】-Java基础知识


    1、Java的工作原理
    1) Java源程序(.java)须要通过编译器编译成字节码(.class)文件;
    2) Java程序的跨平台主要指字节码能够在不论什么具有Java虚拟机的设备上运行;
    3) Java虚拟机的建立须要针对不同的软硬件平台(处理器、操作系统)做专门的实现。


    4) 字节码首先由类装载器载入到Java虚拟机中,其次由字节码校验器检查是否有非法操作,校验通过后再由Java解释器把字节码解释成机器码运行。
    5) Java虚拟机採用沙箱模式运行。即把Java程序的代码和数据限制在一定的内存空间里运行,不同意程序訪问该内存空间外的内存。


    2、八种基本数据类型
    这里写图片描写叙述


    3、基本数据类型间的转换
    1) 自己主动转换:參与运算的数据类型不一致时,精度低的会自己主动向精度高的转换。
    byte-> shortcharintlongfloatdouble
    short->charintlongfloatdouble
    char->intlongfloatdouble
    long->floatdouble
    float->double
    2) 强制转换:强制转换又叫显示转换,有可能造成数据精度的损失。应慎用。


    4、运算符
    算术运算符 ++,–,+,-,*,/,%
    逻辑运算符 &,|,!,^,&&,||
    关系运算符 >,<,==,!=,<=,>=
    位运算符 &,|,^,~,>>,<<,>>>


    5、switch(表达式)
    在Java1.6(包括)之前,表达式仅仅支持能等价成int类型的数据:bytecharshortint,其它类型均不能够。在Java1.7以后,能够支持String类型的数据。


    6、面向对象的特征
    1)封装:把对象的全部属性和全部方法结合成一个独立的单位,并尽可能屏蔽对象的内部细节。


    2)继承:子类拥有父类的全部非private属性和方法,而且子类中还能够添加新的属性和方法。Java支持单继承多实现
    3)重载:同一个类中用同样的方法名定义多个方法,同名方法之间以所带參数个数、參数类型、參数顺序的不同来区分,參数的返回值类型、訪问权限、抛出的异常不构成方法重载的标志。
    4)覆盖:子类中使用与父类同名的方法,且方法的參数(个数、类型、顺序)和返回值类型全然一样,即子类方法的代码覆盖父类方法的代码。被覆盖的方法不能是私有的。
    5)多态:程序中定义的引用变量所指向的详细类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定。

    事实上现机制是:父类或接口定义的引用变量能够指向子类或者详细实现类的实例对象。
    6)子类在隐藏父类的成员后,往往还要用到父类的成员。在子类中引用被隐藏的父类成员时须要用super指明。
    訪问父类方法:super.方法名(參数)
    訪问父类成员:super.成员变量
    调用父类构造方法:super(參数)


    7、抽象类和接口
    1)含有抽象方法的类必须定义成抽象类,抽象类中的方法能够不是抽象方法;
    2)抽象类中定义的抽象方法必须在子类中实现,所以,不能有抽象构造方法和抽象静态方法;
    3)假设子类没有实现抽象父类中的全部抽象方法。那么子类也必须定义成抽象类;
    4)接口能够说是抽象类的一种特例。接口中的全部方法都必须是抽象的。
    5)接口中的方法类型默觉得:public abstract,变量类型默觉得:public static final。
    6)一个类能够实现多个接口。但仅仅能继承一个抽象类。


    8、方法调用时參数传递
    1)值传递:当方法的參数是基本数据类型时是值传递。值传递传递给方法的是參数的数据值,方法接收实际參数的值,但不改变实际參数的值。


    2)引用传递:当方法的參数是对象或者数组时是引用传递。引用传递传递给方法的是參数在内存中的地址,方法中对參数的操作会改变參数的数据值。


    9、作用域 public 。private ,protected 。以及不写时的差别
    说明:假设在元素前面没有写不论什么訪问修饰符,则表示 friendly。
    这里写图片描写叙述


    10、异常
    1)全部的异常都是由Throwable继承而来。分为Error和Exception两类;
    2)Error表示Java运行时系统的内部错误和资源耗尽错误,应用程序不应该抛出这样的类型的异常。
    3)Exception分为两类。全部RuntimeException类及其子类的实例被称为Runtime异常,不属于该范畴的异常则被称为CheckedException。
    4)Java觉得CheckedException是能够被处理的异常。所以Java程序必须显式处理这类异常。假设不处理这类异常。编译时就会错误发生而无法编译;
    5)空指针异常、数组越界异常、类型转换异常、除数为零等都是RuntimeException。


    11、内部类
    1)内部类是指将一个类定义在还有一个类的内部,甚至方法的内部。


    2)内部类能够无条件的訪问其内部声明的成员和外部类的成员。外部类不能直接訪问内部类的成员。
    3)内部类分为静态内部类和非静态内部类。两者的差别例如以下:
    3.1)静态内部类和外部类对象独立。它能够直接创建对象(new Outer.Inner()),也能够通过外部类对象创建对象(outer.new Inner());
    3.2)静态内部类仅仅能使用外部类的静态成员。不能使用外部类的非静态成员,而非静态内部类能够使用外部类的全部成员;
    3.3)静态内部类中能够定义静态成员和非静态成员。非静态内部类中仅仅能定义非静态成员。
    4)匿名类:没有类名的内部类,多用在事件处理的程序中。


    12、Java虚拟机运行时数据区
    1)程序计数器:每一个线程都有自己的程序计数器,它能够看作是线程所运行的字节码的行号指示器;
    2)Java虚拟机栈:描写叙述的是java方法运行内存模型,每一个方法在运行的同一时候都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接、方法出口等信息。
    3)本地方法栈:与Java虚拟机栈差点儿相同。差别是Java虚拟机栈是为运行Java方法服务。本地方法栈是为运行Native方法服务;
    4)Java堆:被全部线程共享的内存区域。全部对象的实例和数组都在堆上分配存储空间;
    5)方法区:也是被全部线程共享的内存区域,用于存储被虚拟机载入的类信息、常量、静态变量等


    13、Equals和==的差别
    ==:比較基本类型变量或者引用类型变量的值是否相等;
    equals:比較引用类型变量相应的对象的内容是否同样;

    String s1 = "qaz";
    String s2 = "qaz";
    String s3 = new String("qaz");
    System.out.println(s1 == s2);             //true 
    System.out.println(s1.equals(s2));         //true
    System.out.println(s1 == s3);             //false
    System.out.println(s1.equals(s3));         //true

    14、String s=new String(“qaz”),创建了几个字符串对象?
    1)”qaz”是一个字符串对象(字符串常量),它存放在常量池中;
    2)new String(“qaz”)会依据字符串常量”qaz”的内容创建一个字符串对象。存放在堆内存中。
    3)在2)运行之前,假设常量池中不存在常量”qaz”,则会在常量池中创建字符串对象”qaz”,否则不用创建。
    综上可知答案为:一个或者两个。


    15、 怎样把一段逗号分隔的字符串转换成一个数组?
    1)用String.spilt(“,”);
    2)用StringTokenizer。代码例如以下:

    String str = "a,bc,d,efg";
            StringTokenizer tokenizer = new StringTokenizer(str, ",");
            String[] words = new String[tokenizer.countTokens()];
            int i = 0;
            while (tokenizer.hasMoreTokens()) {
                words[i++] = tokenizer.nextToken();
            }

    16、Try-catch-finally语句中。finally语句最后运行,即使在try或者catch中已经return了finally语句也会运行;

        public static void main(String[] args) {
            System.out.println(getInt() + "");
        }
        public static int getInt() {
            try {
                return 2;
            } finally {
                return 3;
            }
        }

    ———–运行结果 3——-


    17、类在实例化时成员的初始化顺序
    1)初始化父类的静态成员变量和静态代码块;
    2)初始化子类的静态成员变量和静态代码块;
    3)初始化父类的普通成员变量和代码块;
    4)初始化子类的普通成员变量和代码块。


    18、原码、反码、补码
    1)机器数:一个数在机器中的二进制表示形式叫做机器数。机器数是带符号的,在计算机中用最高位表示符号位,0表示正数。1表示负数。


    2)真值:带符号数在计算机中用补码表示。机器数表示的真实数值叫做真值。
    3)原码:符号位加上真值的绝对值。比方8位二进制数:
    [+1]原=00000001 [-1]原=10000001
    4)反码:正数的反码是其本身,负数的反码是符号位不变。其余各位取反:
    [+1]反=00000001 [-1]反=11111110
    5)补码:正数的补码是其本身。负数的补码是在反码的基础上加一:
    [+1]补=00000001 [-1]补=11111111


    19、左移、右移、无符号右移
    1)左移:向左移动指定位,符号位跟着移动。超出高位截断,低位补0;
    2)右移:向右移动指定位,符号位跟着移动,超出低位截断。高位补符号位;
    3)无符号右移:向右移动指定位,符号位跟着移动,超出低位截断,高位补0;


    20、Java垃圾回收机制
    1)垃圾回收器的任务是回收垃圾对象所占用的空间供新的对象使用。
    2)假设一个对象没有不论什么引用与之关联,那么这个对象就成了可回收的对象;
    3)引用计数法和可达性分析法来推断对象是否还有引用与之关联。
    4)比較常见的将对象判定为可回收对象的情况:
    1、显式的将引用赋值为null;
    2、将已经指向某个对象的引用指向新的对象。
    3、局部引用指向的对象
    4、仅仅有弱引用与之关联的对象。
    5)典型的垃圾回收算法:
    1、Mark-Sweep(标记-清除法):标记阶段标记全部须要被回收的对象,清除阶段回收全部被标记对象占用的空间,这样的方法简单但easy产生内存碎片。
    2、Copying(复制)算法:将内存划分为大小同样的两块,每次使用当中一块。

    当使用的这一块内存满了之后,就将活着的对象拷贝到还有一块内存上,然后回收整块内存。尽管攻克了内存碎片问题。但能够使用的内存缩减为原来的一半。
    3、Mark-Compact(标记-整理法):标记阶段标记全部须要回收的对象。整理阶段将活着的对象移到一端,然后清除边界以外的内存;
    4、Generational Collection(分代收集)算法:该算法是眼下大部分JVM垃圾回收器採用的算法。它将堆内存划分为老年代和新生代,每次垃圾回收时老年代仅仅有少数对象须要回收,新生代中大部分对象都须要回收。

    老年代採用标记-整理法。新生代採用复制法。


    21、对于JVM内存配置參数:-Xmx10240m -Xms10240m -Xmn5120m -XX:SurvivorRatio=3。当中最小内存值和Survivor区总大小各自是(10240)和(2048)。
    1)-Xmx:最大堆大小。
    2)-Xms:初始堆大小,即为最小内存值;
    3)-Xmn:年轻代大小,年轻代由一个Eden区和两个Survivor区组成;
    4)-XX:SurvivorRatio:年轻代中Eden区与Survivor区的大小比值;


    22、 Java内存模型
    Java内存模型规定了JVM有主内存。主内存是多个线程共享的。

    每一个线程都有自己的工作内存,工作内存中保存了该线程用到的变量的主内存拷贝副本,线程对变量的全部操作都必须在工作内存中进行,而不能直接读写主内存中的变量。


    Java内存模型定义了下面八种操作来完毕主内存和工作内存之间的交互:
    (1)Lock(锁定):作用于主内存变量,把一个变量标识为一个线程独占的状态。
    (2)Unlock(解锁):作用于主内存变量。把一个处于锁定状态的变量释放出来。释放后的变量才干被其它线程锁定。
    (3)Read(读取):作用于主内存变量,把一个变量从主内存传输到工作内存;
    (4)Load(载入):作用于工作内存。把从主内存得到的变量值赋给工作内存中的变量副本;
    (5)Use(使用):作用于工作内存。把工作内存变量副本的值传递给运行引擎。
    (6)Assign(赋值):作用于工作内存变量,把从运行引擎接收到的值赋给工作内存中的变量副本;
    (7)Store(存储):作用于工作内存。把工作内存中变量副本的值传输到主内存;
    (8)Write(写入):作用于主内存,把从工作内存得到的变量副本的值赋给主内存中的变量


    23、线程与进程的差别
    1)进程是资源的组织单位,进程中有一个包括了程序内容和数据的地址空间。不同进程的地址空间是相互隔离的;
    2)线程是CPU的调度单位。表示的是程序的运行流程。线程有自己的程序计数器、寄存器、栈和帧等;
    3)引入线程的动机在于堵塞式i/o的存在,当一个线程运行的i/o操作被堵塞时,同一进程的其它线程能够用CPU来进行计算。从而提高了应用的运行效率。


    24、创建线程的方法
    1)通过继承Thread类创建线程;
    2)通过实现Runnable接口创建线程类;
    3)使用Callable和FutureTask创建线程类。


    25、线程的状态转换
    1)新建状态:程序使用new关键字新建一个线程后,该线程处于新建状态。
    2)新建—>就绪:处于新建状态的线程调用start()方法;
    3)就绪—>运行:处于就绪状态的线程得到处理器资源进入运行状态;
    4)运行—>就绪:失去处理器资源或者调用yield()方法;
    5)运行—>堵塞:1、sleep(),2、IO堵塞。3、等待同步锁,4、suspend()方法(易导致死锁);
    6)运行—>死亡:1、run()或call()方法运行完毕,线程正常结束,2、线程抛出一个未捕获的Exception或Error,3、调用stop()方法(易导致死锁);
    7)堵塞—>就绪:1、sleep()时间到。2、IO方法返回,3、获得同步锁。4、resume()。


    26、线程控制
    1)join()方法:调用join()方法的线程完毕run()后再运行join()方法后面的代码。
    2)后台线程:在后台运行,为其它线程提供服务的线程。JVM垃圾回收线程就是典型的后台线程。假设全部的前台线程都死亡了,后台线程会自己主动死亡。
    3)sleep()方法:让线程暂停一段时间,线程转入堵塞状态;
    4)yield()方法:让线程暂停一下,线程转入就绪状态;


    27、相互排斥同步
    1)相互排斥同步是一种常见的并发正确性保障手段。同步是指在多个线程并发訪问共享数据时,共享数据在同一时刻仅仅被一个或者几个(使用信号量的时候)线程訪问。
    2)相互排斥是实现同步的一种手段是方法,同步是相互排斥的目的。

    临界区、相互排斥量、信号量是实现相互排斥的主要方式;
    3)synchronized关键字和重入锁ReentrantLock是实现同步的基本手段,相比synchronized。ReentrantLock添加了一些高级功能,主要有一下3项:
    1、等待可中断:当持有锁的线程长期不释放锁的时候,正在等待的线程能够选择放弃等待。
    2、公平锁:多个线程在等待同一个锁时。必须依照申请锁的时间顺序来依次获得锁。Synchronized锁是非公平的。ReentrantLock默认也是非公平的,但能够使用带布尔值的构造函数要求使用公平锁。
    3、ReentrantLock锁能够绑定多个条件。即一个ReentrantLock对象能够同一时候绑定多个Condition对象。


    28、线程协作
    方式一:wait()、notify()和notifyAll()
    1)wait()、notify()和notifyAll()是Object类中的方法,而且为final方法;
    2)调用某个对象的wait()方法能让当前线程堵塞,而且当前线程必须拥有此对象的monitor;
    3)调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程;
    4)调用notifyAll()方法能够唤醒全部正在等待这个对象的monitor的线程;
    5)这三个方法必须在同步块或者同步方法中运行。notify()和notifyAll()方法仅仅是唤醒等待该对象的monitor的线程,并不决定哪个线程能够获取到monitor。

    方式二:使用Condition的await()、signal()和signalAll()
    1)採用这样的方式实现线程间协作更加安全高效;
    2)Condition是一个接口,基本方法是await()。signal(),signalAll()。
    3)Condition依赖于Lock接口,生成一个Condition的基本代码是lock. new Condition。
    4)Condition的三个基本方法跟wait()、notify()、notifyAll()相应;
    5)调用这三个方法都必须在lock的保护之内。就是说必须在lock.lock()和lock.unlock()之间才干够使用


    29、HashMap和HashTable的差别
    1)HashTable继承Dictionary。HashMap继承AbstractMap。
    2)HashTable的方法是同步的。而HashMap的方法不是同步的。效率上HashMap高于HashTable;
    3)HashMap同意key,value为空。HashTable不同意。


    30、sleep()和wait()的差别
    1)sleep()是定义在Thread类中的方法。wait()是定义在Object类中的方法。
    2)wait()方法仅仅能在同步控制方法或同步控制块中调用。sleep()能够在不论什么地方使用;
    3)sleep()方法没有释放锁,wait()方法释放了锁。使得其它线程能够使用同步代码块。
    4)sleep()方法不出让系统资源。wait()方法出让系统资源。


    31、synchronized关键字
    1)synchronized既保证了多线程的并发有序性,又保证了多线程的内存可见性。


    2)一个线程运行临界区代码步骤例如以下:1 获得同步锁。2 清空工作内存;3 从主内存拷贝变量副本到工作内存。4 对这些变量进行计算;5 将变量从工作内存写回到主存;6 释放锁。
    3)public synchronized void method()这样的情况,锁就是方法所在的对象,public static synchronized void method(),那么锁就是这种方法所在的类。


    32、volatile关键字
    1)volatile仅仅能保证多线程的内存可见性。不能保证多线程的运行有序性
    2)对于volatile修饰的变量。jvm虚拟机仅仅是保证从主内存载入到线程工作内存的值是最新的,并不能解决并发带来的问题。

    比如线程1。线程2 在进行read,load 操作中。发现主内存中count的值都是5,那么都会载入这个最新的值5。

    在线程1对count进行改动之后,会write到主内存中,主内存中的count变量就会变为6。线程2因为已经进行read,load操作,在进行运算之后。也会更新主内存count的变量值为6。即使使用了volatile关键字,也没能解决并发带来的问题。


    33、 写一个单例模式

    public class SingleInstance {
        private SingleInstance() {}
        public static SingleInstance getInstance() {
            return SingleInstanceHolder.INSTANCE;
        }
        private static class SingleInstanceHolder {
            private final static SingleInstance INSTANCE = new SingleInstance();
        }
    }
    public class SingleInstance {
        private volatile static SingleInstance sInstance;
        private SingleInstance() {
        }
        public static SingleInstance getInstance() {
            if (sInstance == null) {
                synchronized (SingleInstance.class) {
                    if (sInstance == null) {
                        sInstance = new SingleInstance();
                    }
                }
            }
            return sInstance;
        }
    }
    public enum SingleInstance {
        INSTANCE;
        private SingleInstance() {
        }
    }

    34、final finally finalize 差别
    1)final:Java中的关键字、修饰符,假设一个类被声明为final。意味着它不能派生出新的子类,不能作为父类被继承,因此一个类不能同一时候声明为abstract和final。被声明为final的变量必须在声明时给定初始值,在以后的使用中仅仅能读取不能改动。被声明为final的方法仅仅能使用。不能重载。
    2)finally:try-catch-finally异常处理语句的一部分,finally结构里的代码总会运行,而无论有无异常发生。关闭数据库连接的close()方法通常放在finally中。
    3)finalize:Java中的一个方法。在Object类中定义的,finalize()方法在垃圾收集器将对象从内存中清除出去前。做必要的清理工作。


    35,Linux下权限相应的数字为:
    r =4, w =2, x =1
    6就是rw-
    4就是r–
    5就是r-x


    36。TCP三次握手
    简化一下,client发送X。server发送Y。三次握手各自是:
    client:发送X
    服务端:发送Y, 确认X+1
    client:发送X+1。确认Y+1

  • 相关阅读:
    浅谈GET和POST请求方式
    浅淡建立bitmap实例
    从.NET1.1升级到.NET2.0时出现的PInvokeStackImbalance错误
    为RichTextBox添加快捷功能菜单(复制,粘贴,全选等)
    针对解决sql server数据库中不区分大小写问题.
    <转>用C#创建可拖动窗体
    如何:对 Windows 窗体控件进行线程安全调用
    正则
    <转>反射的第二部分:Emit
    『励志』一些普通又具有深刻哲理的警句(转载)
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7221032.html
Copyright © 2020-2023  润新知