1、Java的IO操作中有面向字节(Byte)和面向字符(Character)两种方式。
- 面向字节的操作为以8位为单位对二进制的数据进行操作,对数据不进行转换,这些类都是InputStream和OutputStream的子类。
- 面向字符的操作为以字符为单位对数据进行操作,在读的时候将二进制数据转为字符,在写的时候将字符转为二进制数据,这些类都是Reader和Writer的子类。
-
总结:以InputStream(输入)/OutputStream(输出)为后缀的是字节流;
以Reader(输入)/Writer(输出)为后缀的是字符流。
-
2、不通过构建函数也可以创建对象
Java创建对象的几种方式:
- (1) 用new语句创建对象,这是最常见的创建对象的方法。
- (2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
- (3) 调用对象的clone()方法。
- (4) 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。
(1)和(2)都会明确的显式的调用构造函数 ;
(3)是在内存上对已有对象的影印,所以不会调用构造函数 ;
(4)是从文件中还原类的对象,也不会调用构造函数。
3、模块之间的耦合程度反映了模块的独立性,也反映了系统分解后的复杂程度。 按照耦合程度从弱到强,可以将其分成7级。
分别是 非直接耦合、数据耦合、标记耦合、控制耦合、外部耦合、公共耦合和内容耦合。
4、Java异常的基类为java.lang.Throwable,java.lang.Error和java.lang.Exception继承 Throwable,RuntimeException和其它的Exception等继承Exception,具体的RuntimeException继承RuntimeException。
扩展:错误和异常的区别(Error vs Exception)
- 1) java.lang.Error: Throwable的子类,用于标记严重错误。合理的应用程序不应该去try/catch这种错误。绝大多数的错误都是非正常的,就根本不该出现的。
- java.lang.Exception: Throwable的子类,用于指示一种合理的程序想去catch的条件。即它仅仅是一种程序运行条件,而非严重错误,并且鼓励用户程序去catch它。
- 2) Error和RuntimeException 及其子类都是未检查的异常(unchecked exceptions),而所有其他的Exception类都是检查了的异常(checked exceptions).
- checked exceptions: 通常是从一个可以恢复的程序中抛出来的,并且最好能够从这种异常中使用程序恢复。比如FileNotFoundException, ParseException等。检查了的异常发生在编译阶段,必须要使用try…catch(或者throws)否则编译不通过。
- unchecked exceptions: 通常是如果一切正常的话本不该发生的异常,但是的确发生了。发生在运行期,具有不确定性,主要是由于程序的逻辑问题所引起的。比如ArrayIndexOutOfBoundException, ClassCastException等。从语言本身的角度讲,程序不该去catch这类异常,虽然能够从诸如RuntimeException这样的异常中catch并恢复,但是并不鼓励终端程序员这么做,因为完全没要必要。因为这类错误本身就是bug,应该被修复,出现此类错误时程序就应该立即停止执行。 因此,面对Errors和unchecked exceptions应该让程序自动终止执行,程序员不该做诸如try/catch这样的事情,而是应该查明原因,修改代码逻辑。
- RuntimeException:RuntimeException体系包括错误的类型转换、数组越界访问和试图访问空指针等等。
- 处理RuntimeException的原则是:如果出现 RuntimeException,那么一定是程序员的错误。例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。其他(IOException等等)checked异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。
5、equals和==的区别
“==”比较的是值【变量(栈)内存中存放的对象的(堆)内存地址】
equal用于比较两个对象的值是否相同【不是比地址】
【特别注意】Object类中的equals方法和“==”是一样的,没有区别,而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同”,所以,当自己创建类时,自动继承了Object的equals方法,要想实现不同的等于比较,必须重写equals方法。
"=="比"equal"运行速度快,因为"=="只是比较引用.
6、普通的类方法是可以和类名同名的,和构造方法唯一的区分就是,构造方法没有返回值。(不推荐普通类方法和类名同名)
7、存在使i + 1 < i的数吗()
答案:存在
解析:如果i为int型,那么当i为int能表示的最大整数时,i+1就溢出变成负数了,此时不就<i了吗。
扩展:存在使i > j || i <= j不成立的数吗()
答案:存在
解析:比如Double.NaN或Float.NaN(NaN,Not a Number)
8、Java接口的修饰符可以为 final 、 abstract
(1)接口用于描述系统对外提供的所有服务,因此接口中的成员常量和方法都必须是公开(public)类型的,确保外部使用者能访问它们;
(2)接口仅仅描述系统能做什么,但不指明如何去做,所以接口中的方法都是抽象(abstract)方法;
(3)接口不涉及和任何具体实例相关的细节,因此接口没有构造方法,不能被实例化,没有实例变量,只有静态(static)变量;
(4)接口的中的变量是所有实现类共有的,既然共有,肯定是不变的东西,因为变化的东西也不能够算共有。所以变量是不可变(final)类型,也就是常量了。
(5) 接口中不可以定义变量?如果接口可以定义变量,但是接口中的方法又都是抽象的,在接口中无法通过行为来修改属性。有的人会说了,没有关系,可以通过 实现接口的对象的行为来修改接口中的属性。这当然没有问题,但是考虑这样的情况。如果接口 A 中有一个public 访问权限的静态变量 a。按照 Java 的语义,我们可以不通过实现接口的对象来访问变量 a,通过 A.a = xxx; 就可以改变接口中的变量 a 的值了。正如抽象类中是可以这样做的,那么实现接口 A 的所有对象也都会自动拥有这一改变后的 a 的值了,也就是说一个地方改变了 a,所有这些对象中 a 的值也都跟着变了。这和抽象类有什么区别呢,怎么体现接口更高的抽象级别呢,怎么体现接口提供的统一的协议呢,那还要接口这种抽象来做什么呢?所以接口中 不能出现变量,如果有变量,就和接口提供的统一的抽象这种思想是抵触的。所以接口中的属性必然是常量,只能读不能改,这样才能为实现接口的对象提供一个统 一的属性。
通俗的讲,你认为是要变化的东西,就放在你自己的实现中,不能放在接口中去,接口只是对一类事物的属性和行为更高层次的抽象。对修改关闭,对扩展(不同的实现 implements)开放,接口是对开闭原则的一种体现。
所以:
接口的方法默认是public abstract;
接口中不可以定义变量即只能定义常量(加上final修饰就会变成常量)。所以接口的属性默认是public static final 常量,且必须赋初值。
注意:final和abstract不能同时出现。
9、默认ArrayList的长度是10个
10、
- 对称加密:
对称加密采用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥加密,也就是密钥也可以用作解密密钥,这种方法在密码学中叫做对称加密算法,对称加密算法使用起来简单快捷,密钥较短,且破译困难,除了数据加密标准(DES),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,而且对计算机功能要求也没有那么高
常用的对称加密算法有:DES、3DES、RC2、RC4、RC5、RC6、AES、Blowfish、IDEA
- 非对称加密技术:
与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。
公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。
非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。
常用的非对称加密算法有:RSA、DSA(数字签名用)、ECC(移动设备用)、Diffie-Hellman、El Gamal、
- Hash算法(摘要算法)(单向散列函数)
Hash算法特别的地方在于它是一种单向算法,用户可以通过hash算法对目标信息生成一段特定长度的唯一hash值,却不能通过这个hash值重新获得目标信息。因此Hash算法常用在不可还原的密码存储、信息完整性校验等。
常见的Hash算法有MD2、MD4、MD5、HAVAL、SHA
11、下面程序的运行结果是什么()
class HelloA {
public HelloA() {
System.out.println("HelloA");
}
{ System.out.println("I'm A class"); }
static { System.out.println("static A"); }
}
public class HelloB extends HelloA {
public HelloB() {
System.out.println("HelloB");
}
{ System.out.println("I'm B class"); }
static { System.out.println("static B"); }
public static void main(String[] args) {
new HelloB();
}
}
答案:
static A
static B
I'm A class
HelloA
I'm B class
HelloB
考查静态语句块、构造语句块(就是只有大括号的那块)以及构造函数的执行顺序。
对象的初始化顺序:(1)类加载之后,按从上到下(从父类到子类)执行被static修饰的语句;(2)当static语句执行完之后,再执行main方法;(3)如果有语句new了自身的对象,将从上到下执行构造代码块、构造器(两者可以说绑定在一起)。
12、Java中所有定义的基本类型或对象都必须初始化才能输出值
public static void main (String[] args){
String s;
System.out.println("s=" + s);
} // 由于String s没有初始化,代码不能编译通过
13、抽象类和接口的区别:
(1)接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的。
(2)abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface。接口还有标识(里面没有任何方法,如Remote接口)和数据共享(里面的变量全是常量)的作用。
(3)在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是 static final的,不过在 interface中一般不定义数据成员),所有的成员方法默认都是 public abstract 类型的。
(4)abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"is-a"关系,interface表示的是"has-a"关系。
(5)实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法,一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。抽象类中可以有非抽象方法。接口中则不能有实现方法。
(6)接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。抽象类中的变量默认是 friendly 型,其值可以在子类中重新定义,也可以在子类中重新赋值。
14、父类与子类的构造函数调用次序
第一个规则:子类的构造过程中,必须调用其父类的构造方法。一个类,如果我们不写构造方法,那么编译器会帮我们加上一个默认的构造方法(就是没有参数的构造方法),但是如果你自己写了构造方法,那么编译器就不会给你添加了,所以有时候当你new一个子类对象的时候,肯定调用了子类的构造方法,但是如果在子类构造方法中我们并没有显示的调用基类的构造方法,如:super(); 这样就会调用父类没有参数的构造方法。
第二个规则:如果子类的构造方法中既没有显示的调用基类构造方法,而基类中又没有无参的构造方法,则编译出错,所以,通常我们需要显示的:super(参数列表),来调用父类有参数的构造函数,此时无参的构造函数就不会被调用。
总之,一句话:子类没有显示调用父类构造函数,不管子类构造函数是否带参数都默认调用父类无参的构造函数,若父类没有则编译出错。
15、面向对象的三个基本特征是:封装、继承、多态。