银杏叶好看嘛
1. 为什么 Java 中用 char 数组比 String 更适合存储密码
由于字符串在 Java 中是不可变的,如果你将密码存储为纯文本,它将在内存中可用,直到垃圾收集器清除它,并且为了可重用性,会存在 String 在字符串池中,它很可能会保留在内存中持续很长时间,从而构成安全威胁。
由于任何有权访问内存转储的人都可以以明文形式找到密码,这是另一个原因,你应该始终使用加密密码而不是纯文本。
由于字符串是不可变的,所以不能更改字符串的内容,因为任何更改都会产生新的字符串,而如果你使用char[],你就可以将所有元素设置为空白或零。
因此,在字符数组中存储密码可以明显降低窃取密码的安全风险。
2. 为什么Java中不支持多重继承
多继承虽然能使子类同时拥有多个父类的特征,但是其缺点也是很显著的,主要有两方面:
(1) 如果在一个子类继承的多个父类中拥有相同名字的实例变量,子类在引用该变量时将产生歧义,无法判断应该使用哪个父类的变量
(2) 如果在一个子类继承的多个父类中拥有相同方法,子类中有没有覆盖该方法,那么调用该方法时将产生歧义,无法判断应该调用哪个父类的方法
正因为有以上的致命缺点,所以java中禁止一个类继承多个父类。
参考文档:
1) chrome-extension://cdonnmffkdaoajfknoeeecmchibpmkmg/static/pdf/web/viewer.html?file=https%3A%2F%2Fwww.cs.dartmouth.edu%2F~mckeeman%2Fcs118%2Freferences%2FOriginalJavaWhitepaper.pdf
2)https://www.zhihu.com/question/24317891
3)https://www.breakyizhan.com/java/4226.html
3. 死锁与活锁的区别,死锁与饥饿的区别
死锁:是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
产生死锁的必要条件:
互斥条件:所谓互斥就是进程在某一时间内独占资源。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
不剥夺条件: 进程已获得资源,在末使用完之前,不能强行剥夺。
循环等待条件: 若干进程之间形成一种头尾相接的循环等待资源关系。
活锁:任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败。
活锁和死锁的区别在于:
处于活锁的实体是在不断的改变状态,所谓的“活”;而处于死锁的实体表现为等待;
活锁有可能自行解开,死锁则不能。
文字看得累?来个简易图:
看下图,死锁是这样的:大家都要先走,然后都走不了。
而活锁则是:大家都让别人先走,然后还是都没走 -。-
饥饿:一个或者多个线程因为种种原因无法获得所需要的资源,导致一直无法执行的状态。(一直好饿……)
Java中导致饥饿的原因:
高优先级线程吞噬所有的低优先级线程的CPU时间。
线程被堵塞在一个等待进入同步块的状态,因为其他线程总是能在它之前持续地对该同步块进行访问。
线程在等待一个本身也处于等待完成的对象(比如调用这个对象的wait方法),因为其他线程总是被持续地获得唤醒。
4. Java中的异常处理机制的简单原理和应用
异常是指java程序运行时(非编译)所发生的非正常情况或错误,与现实生活中的事件很相似,现实生活中的事件可以包含事件发生的时间、地点、人物、情节等信息,可以用一个对象来表示,Java使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象来表示的,该对象中包含有异常的信息。
Java对异常进行了分类,不同类型的异常分别用不同的Java类表示。
所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类:Error和Exception。
Error表示应用程序本身无法克服和恢复的一种严重问题,程序只有死的份了,例如,说内存溢出和线程死锁等系统问题。
Exception表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常。
系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);
普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。
java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,而系统异常可以处理也可以不处理,所以,编译器不强制用try..catch处理或用throws声明,所以系统异常也称为unchecked异常。
5. synchronized和volatile关键字的作用
一旦一个共享变量(类的成员变量、类的静态成员变量)被 volatile修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2)禁止进行指令重排序。
volatile本质是在告诉JVM当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
1. volatile 仅能使用在变量级别;synchronized则可以使用在变量、方法和类级别的
2. volatile 仅能实现变量的修改可见性,并不能保证原子性;synchronized则可以保证变量的修改可见性和原子性
3. volatile 不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
4. volatile 标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化