java

1、面向对象程序设计具有以下特点

封装性:封装是面向对象编程的核心思想。将对象的属性和行为封装起来,其载体就是类,类通常对客户隐藏其实现细节。(高内聚,低耦合)
继承性:主要是实现了代码的复用。
多态性:同一个操作,作用于不同的对象,会产生不同的结果。
父类的引用指向子类的对象。实现多态需要做两件事:1). 方法重写(子类继承父类并重写父类中的方法);2). 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)

2.类—》对象—》属性(全局变量/成员变量/field){声明在类体中}—》方法

(method方法中不可以再定义方法)—》局部变量{声明在方法体中,只在该方法中有效}(成员变量有默认初始化值,局部变量没有默认初始化值,则调用局部变量前一定要先赋值)
实列变量:int x = 45
成员变量
静态变量:static int y=20(静态变量属于类所有也可跨类使用,以 类名.静态变量名 的方式使用。(静态方法、静态常量也一样,但静态成员同样遵循着public、private和protected修饰符的约束。))不能将方法体中的变量声明为Static

类变量也叫静态变量,也就是在变量前加了static 的变量;
实例变量也叫对象变量,即没加static 的变量;
区别在于:
类变量和实例变量的区别在于:类变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果;而实例变量则属对象私有,某一个对象将其值改变,不影响其他对象;

在Java语言中对静态方法有两点规定:
在静态方法中不可以使用this关键宇。
在静态方法中不可以直接调用非静态方法。(主方法就是静态的,所以主方法中直接调用的方法也必须是静态的,可先创建对象,通过对象调用非静态方法。)
局部变量可以与成员变量名字相同,此时成员变量将被隐藏,即成员变量在此方法中暂时失效。若要在方法体中引用成员变量可用“this.变量名”引用
this关键宇和对象都可以调用成员变量和成员方法,this引用的就是 本类的一个对象。
在相互不嵌套的作用域中可以同时声明两个名称和类型相同的局部变量,

static:静态变量、静态代码块(调用静态变量和静态方法)、静态方法(只能使用静态变量)
final:修饰类不能被继承、修饰方法不能被重写,修饰属性为常量
final static变量即为全局常量

3、权限修饰符

在这里插入图片描述
接口里的变量都隐式声明为 public static final,而接口里的方法默认情况下访问权限为 public。
类的权限设定会约束类成员的权限设定。
局部变量不可使用权限修饰符。

4、赋值 和 new的区别:

其实这是对存储、堆和栈的问题,如果直接赋值它在栈中的位置不变,只是堆里的数据有变化,如果new 了 则是先在栈中添加数据 ,然后再在堆里添加数据 ,栈的数据指向堆中数据。

5、抽象类与接口的区别

(一) 继承方面:
(1) 抽象类只能单继承;接口可以多实现
(二) 成员属性方面:
(1) 抽象类中可以有普通属性,也可以有常量
(2) 接口中的成员变量全部默认是常量,使用public static final修饰,这个可以省略不写
(三) 构造函数方面:
(1) 接口不能有构造函数
(2) 抽象类可以有构函数,但是这里的构造函数不是用来创建对象的,而且用来被实现类调用进行初始化操作的
(四) 方法方面:
抽象类中允许有具体实现的方法,而接口则所有方法必为抽象方法

相同之处:
(1) 接口与抽象类都不能被实例化,需要被其他进行实现或继承
(2) 接口与抽象类里面都能包含抽象方法,实现接口或继承抽象类的子类都必须实现这些抽象方法

6、内部类

内部类

7、异常

异常
Throwable 是所有异常的父类,它有两个直接子类 Error 和 Exception,其中 Exception 又被继续划分为被检查的异常(checked exception)和运行时的异常(runtime exception,即不受检查的异常);Error 表示系统错误,通常不能预期和恢复(譬如 JVM 崩溃、内存不足等);被检查的异常(Checked exception)在程序中能预期且要尝试修复(如我们必须捕获 FileNotFoundException 异常并为用户提供有用信息和合适日志来进行调试,Exception 是所有被检查的异常的父类);运行时异常(Runtime Exception)又称为不受检查异常,譬如我们检索数组元素之前必须确认数组的长度,否则就可能会抛出 ArrayIndexOutOfBoundException 运行时异常,RuntimeException 是所有运行时异常的父类。

final, finally, finalize的区别?
final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承。
finally是异常处理语句结构的一部分,表示总是执行。
finalize()方法是Object类中提供的一个方法,在GC准备释放对象所占用的内存空间之前,它将首先调用finalize()方法。finalize()方法中一般用于释放非Java 资源(如打开的文件资源、数据库连接等),或是调用非Java方法(native方法)时分配的内存(比如C语言的malloc()系列函数)。

Java 中什么是异常链?
异常链是指在进行一个异常处理时抛出了另外一个异常,由此产生了一个异常链条,大多用于将受检查异常(checked exception)封装成为非受检查异常(unchecked exception)或者 RuntimeException。特别注意如果你因为一个异常而决定抛出另一个新的异常时一定要包含原有的异常,这样处理程序才可以通过 getCause() 和 initCause() 方法来访问异常最终的根源

try-catch-finally-return执行顺序?
不管是否有异常产生,finally块中代码都会执行
当try和catch中有return语句时,finally块仍然会执行
finally是在return后面的表达式运算执行的,所以函数返回值在finally执行前确定的,无论finally中的代码怎么样,返回的值都不会改变,仍然是之前return语句中保存的值
finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值

8、Java基本类型共有八种,

基本类型可以分为三类,字符类型char(2字节),布尔类型boolean以及数值类型byte、short、int、long、float、double
声明long型变量必须以l或L结尾,浮点型常量默认为double ,声明为float型常量须后加f或F.。
引用数据类型:数组、接口、类

9、== 和 equals 的区别?

= = 如果比较的对象是基本数据类型,则比较的是数值是否一致;如果比较的是引用数据类型,则比较的是对象的地址值是否一致。
equals():equals()方法不能用于比较基本数据类型的对象,如果对象和自身进行比较,则equals()方法与==是一样的。对于String类 Date类 File类等 可重写equals() 方法用于比较对象的属性内容是否一致。

10、jvm

JRE/JDK/JVM是什么关系?
JRE是Java运行环境,即(Java Runtime Environment),也就是Java平台。所有的Java程序都要在JRE下才能运行。
JDK是开发工具包,即(Java Development Kit),它是程序开发者用来编译、调试Java程序,它也是Java程序,也需要JRE才能运行。
JVM是Java虚拟机,即(Java Virual Machine),它是JRE的一部分,一个虚构出来的计算机,它支持跨平台。
JVM被分为三个主要的子系统
(1)类加载器子系统(2)运行时数据区(3)执行引擎
类加载
在这里插入图片描述
加盐准细化

  1. 运行时数据区(Runtime Data Area)
    The 运行时数据区域被划分为5个主要组件:

2.1 方法区(Method Area)
所有类级别数据将被存储在这里,包括静态变量。每个JVM只有一个方法区,它是一个共享的资源。

2.2 堆区(Heap Area)
所有的对象和它们相应的实例变量以及数组将被存储在这里。每个JVM同样只有一个堆区。由于方法区和堆区的内存由多个线程共享,所以存储的数据不是线程安全的。

2.3 栈区(Stack Area)
对每个线程会单独创建一个运行时栈。对每个函数呼叫会在栈内存生成一个栈帧(Stack Frame)。所有的局部变量将在栈内存中创建。栈区是线程安全的,因为它不是一个共享资源。栈帧被分为三个子实体:

a 局部变量数组 – 包含多少个与方法相关的局部变量并且相应的值将被存储在这里。

b 操作数栈 – 如果需要执行任何中间操作,操作数栈作为运行时工作区去执行指令。

c 帧数据 – 方法的所有符号都保存在这里。在任意异常的情况下,catch块的信息将会被保存在帧数据里面。

2.4 PC寄存器
每个线程都有一个单独的PC寄存器来保存当前执行指令的地址,一旦该指令被执行,pc寄存器会被更新至下条指令的地址。

2.5 本地方法栈
本地方法栈保存本地方法信息。对每一个线程,将创建一个单独的本地方法栈。

  1. 执行引擎
    分配给运行时数据区的字节码将由执行引擎执行。执行引擎读取字节码并逐段执行。

3.1 解释器:
解释器能快速的解释字节码,但执行却很慢。 解释器的缺点就是,当一个方法被调用多次,每次都需要重新解释。

[GC]
GC垃圾收集算法:

标记—清除算法:有两点不足,一个效率问题,标记和清除过程都效率不高;一个是空间问题,标记清除后会产生大量不连续的内存碎片;
复制算法:解决了内存碎片问题,但是内存利用率低;
标记整理算法:解决了内存碎片问题

收集器:Serial收集器、并行收集器、CMS收集器、G1收集器。

11、设计模式

12、包装类

由基本类型向对应的包装类转换称为装箱,例如把 int 包装成 Integer 类的对象;包装类向对应的基本类型转换称为拆箱,例如把 Integer 类的对象重新简化为 int。

13、jdbc

14、反射

15、序列化

16、IO

IO

17、集合

集合
集合最全

18、进程和线程

进程间通信和线程间的通信

线程池

进程与线程:
根本区别:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位

资源开销:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

包含关系:如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

内存分配:同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源是相互独立的

影响关系:一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。

执行过程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,两者均可并发执行

线程、进程与jvm之间的关系

Java编写的程序都运行在在Java虚拟机(JVM)中,每用java命令启动一个java应用程序,就会启动一个JVM进程。在同一个JVM进程中,有且只有一个进程,就是它自己。在这个JVM环境中,所有程序代码的运行都是以线程来运行的。JVM找到程序程序的入口点main(),然后运行main()方法,这样就产生了一个线程,这个线程称之为主线程。当main方法结束后,主线程运行完成。JVM进程也随即退出。

从 JVM 角度说进程和线程之间的关系

一个Java应用程序java.exe,至少有三个线程:main()主线程,gc()垃圾回收线程,异常处理线程。

并行:多个cpu同时执行多个任务
并发:一个cpu(采用)时间片同时执行多个任务,秒杀,多人做同一件事。

19、多线程

常见面试题
创建一个线程
Java 提供了三种创建线程的方法:
通过实现 Runnable 接口;
通过继承 Thread 类本身;
通过 Callable 和 Future 创建线程。

线程生命周期:
新建状态:
使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。

就绪状态:
当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。

运行状态:
如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

阻塞状态:
如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:

等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。

同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。

其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。

死亡状态:
一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

同步以及死锁
一个多线程的程序如果是通过 Runnable 接口实现的,则意味着类中的属性被多个线程共享,那么这样就会造成一种问题,如果这多个线程要操作同一个资源时就有可能出现资源同步问题。

解决方法:1.同步代码块
2.同步方法(使用 synchronized 关键字将一个方法声明为同步方法。)

死锁

同步可以保证资源共享操作的正确性,但是过多同步也会产生问题。例如,现在张三想要李四的画,李四想要张三的书,张三对李四说“把你的画给我,我就给你书”,李四也对张三说“把你的书给我,我就给你画”两个人互相等对方先行动,就这么干等没有结果,这实际上就是死锁的概念。

所谓死锁,就是两个线程都在等待对方先完成,造成程序的停滞,一般程序的死锁都是在程序运行时出现的。

线程间通信:
Java为每个Object都实现了wait()和notify(),notifyAll()方法
wait()方法可以使调用该方法的线程释放共享资源的锁,然后从运行状态退出,进入等待队列,直到被再次唤醒。

notify()方法可以随机唤醒等待队列中等待同一共享资源的“一个”线程,并使该线程退出等待队列,进入可运行状态,也就是notify()方法仅通知“一个”线程。

notifyAll()方法可以使所有正在等待队列中等待统一共享资源的“全部”线程从等待状态退出,进入可运行状态。此时,优先级最高的那个线程最先执行,但也有可能是随机执行,因为这要取决于JVM虚拟机的实现。

线程的调度

1、调整线程优先级:Java线程有优先级,优先级高的线程会获得较多的执行机会。

Java线程的优先级用整数表示,取值范围是1~10。Thread类有以下三个静态常量:
static int MAX_PRIORITY
线程能够具有的最高优先级,取值为10。
static int MIN_PRIORITY
线程能够具有的最低优先级,取值为1。
static int NORM_PRIORITY
分配给线程的默认优先级。取值为5。

Thread类的setPriority()和getPriority()方法分别用来设置和获取线程的优先级。
每一个线程都有默认的优先级。主线程的默认优先级为Thread.NORM_PRIORITY。
线程的优先级有继承关系,比方A线程中创建了B线程。那么B将和A具有同样的优先级。
JVM提供了10个线程优先级,但与常见的操作系统都不能非常好的映射。假设希望程序能移植到各个操作系统中,应该仅仅使用Thread类有以下三个静态常量作为优先级,这样能保证同样的优先级採用了同样的调度方式。

2、线程睡眠:Thread.sleep(long millis)方法,使线程转到堵塞状态。
millis參数设定睡眠的时间。以毫秒为单位。当睡眠结束后,就转为就绪(Runnable)状态。sleep()平台移植性好。

3、线程等待:Object类中的wait()方法,导致当前的线程等待,直到其它线程调用此对象的 notify() 方法或 notifyAll() 唤醒方法。这个两个唤醒方法也是Object类中的方法,行为等价于调用 wait(0) 一样。

4、线程让步:Thread.yield() 方法。暂停当前正在执行的线程对象。把执行机会让给同样或者更高优先级的线程。

5、线程添加:join()方法。等待其它线程终止。
在当前线程中调用还有一个线程的join()方法,则当前线程转入堵塞状态。直到还有一个进程执行结束,当前线程再由堵塞转为就绪状态。

6、线程唤醒:Object类中的notify()方法,唤醒在此对象监视器上等待的单个线程。假设全部线程都在此对象上等待。则会选择唤醒当中一个线程。选择是随意性的。并在对实现做出决定时发生。线程通过调用当中一个 wait 方法,在对象的监视器上等待。 直到当前的线程放弃此对象上的锁定。才干继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其它全部线程进行竞争;比如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。相似的方法还有一个notifyAll(),唤醒在此对象监视器上等待的全部线程。

sleep()和yield()的差别
sleep()和yield()的差别):sleep()使当前线程进入停滞状态。所以执行sleep()的线程在指定的时间内肯定不会被执行;yield()仅仅是使当前线程又一次回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
sleep 方法使当前执行中的线程睡眼一段时间,进入不可执行状态,这段时间的长短是由程序设定的。yield 方法使当前线程让出 CPU 占有权,但让出的时间是不可设定的。实际上,yield()方法对应了例如以下操作:先检測当前是否有同样优先级的线程处于同可执行状态,如有。则把 CPU 的占有权交给此线程,否则,继续执行原来的线程。所以yield()方法称为“退让”,它把执行机会让给了同等优先级的其它线程
另外。sleep 方法同意较低优先级的线程获得执行机会。但 yield() 方法执行时,当前线程仍处在可执行状态,所以。不可能让出较低优先级的线程些时获得 CPU 占有权。

什么是线程安全?如何保证线程安全?

线程安全:
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。

如何保证呢:
1、使用线程安全的类;
2、使用synchronized同步代码块,或者用Lock锁;

由于线程安全问题,使用synchronized同步代码块
原理:当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。
另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
3、多线程并发情况下,线程共享的变量改为方法局部级变量;

. 什么是线程池?
线程池其实就是将多个线程对象放到一个容器当中。

为什么使用线程池?
可以重用线程,减少创建和销毁线程带来的消耗。

如何避免死锁?
避免死锁最简单的方法就是阻止循环等待条件,将系统中所有的资源设置标志位、排序,规定所有的进程申请资源必须以一定的顺序(升序或降序)做操作来避免死锁。

20、 jdk8新特性

jdk8新特性

21、数据结构:

22、排序

快排

public class quicksort {
    public static void quickSort(int[] arr,int low,int high){
        int i,j,temp;
        if(low>high){
            return;
        }
        i=low;
        j=high;
        temp = arr[low];
        while (i<j) {
            //先看右边,依次往左递减
            while (temp<=arr[j]&&i<j) {
                j--;
            }
            //再看左边,依次往右递增
            while (temp>=arr[i]&&i<j) {
                i++;
            }
            //如果满足条件则交换
            if (i<j) {
                int z = arr[i];
                arr[i] = arr[j];
                arr[j] = z;
            }
        }

        //最后将基准为与i和j相等位置的数字交换
        arr[low] = arr[i];
        arr[i] = temp;
        //递归调用左半数组
        quickSort(arr, low, j-1);
        //递归调用右半数组
        quickSort(arr, j+1, high);
    }


    public static void main(String[] args){
        int[] arr = {10,7,2,4,7,62,3,4,2,1,8,9,19};
        quickSort(arr, 0, arr.length-1);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

归并

public class MergeSort {
    public static void main(String[] args) {
        int[] arr = new int[]{4,8,9,3,44,55,3,22,1,44,3};
        sort(arr,0,arr.length-1);
        for(int i:arr){
            System.out.println(i);
        }
    }

    public static void sort(int[] arr,int left,int right) {
        if(left<right){
            int mid=(left+right)/2;
            sort(arr,left,mid);
            sort(arr,mid+1,right);
            merge(arr,left,mid,right);
        }
    }

    public static void merge(int[] arr,int left,int mid,int right) {
        int[] tmp=new int[arr.length];
        int p1=left;
        int p2=mid+1;
        int k=left;
        while(p1<=mid && p2<=right){
            if(arr[p1]<arr[p2]){
                tmp[k++]=arr[p1++];
            }else{
                tmp[k++]=arr[p2++];
            }
        }
        while(p1<=mid){
            tmp[k++]=arr[p1++];
        }
        while(p2<=right){
            tmp[k++]=arr[p2++];
        }
        for(int i=left;i<=right;i++){
            arr[i]=tmp[i];
        }

    }
}

23、spring

.spring
IoC:(inverse of control,控制反转),原先由程序员主动通过new来实例化对象,现在转交给spring负责。
IoC最大作用:解耦
DI:(dependency inject,依赖注入),当一个类A中需要依赖另一个类B对象时,把B赋值给A的过程。
AOP:(aspect oriented programming,面向切面编程),在程序原有纵向逻辑中,针对某一个或某些方法添加通知,形成横切面的过程。
AOP底层原理:代理设计模式。代理设计模式有:静态代理设计模式、JDK动态代理和CgLib动态代理。
JDK动态代理:利用反射机制,效率不高;
CgLib动态代理:基于字节码,生成真实对象的子类,不需要实现接口,运行效率高于JDK动态代理,非JDK功能,需要额外导入jar。

spring
springmvc
mybatis

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值