- 面向对象都有哪些特性以及一对这些特性的理解
(1) 继承:继续传承,就是上一代的东西留给了下一代。在java中就是一个类把自己的东西(如属性方法等)提供给了另外一个类。提供东西的类叫父类,得到东西的类叫子类。继承优点:可复用性可扩展性。
(2) 封装:密封包装,把不想对外公开的东西加个锁密封起来,只有拥有相应钥匙才能解开锁看到隐藏的东西。在java中就是把数据隐藏起来,只对外提供简单的编程接口以便进行访问。
(3) 多态:多种形态,就好像回答同一个问题可以有多种不同的答案。在java中就是同一对象调用同一方法做出了不同的事情。多态分为编译时多态(如方法重载)和运行时多态(如方法重写)。实现运行时多态需要两个条件:一时方法重写,二时子类对象要指向父类的引用。
(4) 抽象:抽取对象,将一类对象的共同特征抽取出来形成一个新类,包括数据抽象和行为抽象,只关注对象的属性和行为,不关注行为的细节。
- 访问权限修饰符public、protected、default、private的区别
修饰符 |
当前类 |
同包 |
子类 |
不同包 |
public |
√ |
√ |
√ |
√ |
protected |
√ |
√ |
√ |
× |
default |
√ |
√ |
× |
× |
private |
√ |
× |
× |
× |
- new 一个对象的过程和 clone 一个对象的过程区别
(1) 在java中clone()与new都能创建对象。
(2) clone()不会调用构造方法;new会调用构造方法。
(3) clone()能快速创建一个已有对象的副本,即创建对象并且将已有对象中所有属性值克隆;new只能在JVM中申请一个空的内存区域,对象的属性值要通过构造方法赋值。
注意:
① 使用clone()类必须实现java.lang.Cloneable接口并重写Object类的clone()方法,如果没有实现Cloneable()接口将会抛出CloneNotSupportedException异常。(此类实现java.lang.Cloneable接口,指示Object.clone()方法可以合法的对该类实例进行按字段复制。)
② 默认的Object.clone()方法是浅拷贝,创建好对象的副本然后通过“赋值”拷贝内容,如果类包含引用类型成员变量,那么原始对象和克隆对象的引用类型成员变量将指向相同的引用内容。
- 什么是浅拷贝?什么是深拷贝?
(1) “浅拷贝”:默认的Object.clone()方法,将原对象的引用拷贝给新对象,即新对象与原对象指向同一个地址值,并没有在堆中开辟新的内存空间。
(2) “深拷贝”:重写clone()方法,是拷贝原对象的同时连同原对象的引用一起拷贝,原对象与新对象分别指向不同的引用地址值。深拷贝重新在堆中开辟新的内存空间。
注意:如果要深拷贝一个对象,这个对象必须要实现Cloneable()接口,实现clone方法。并且在 clone 方法内部,把该对象引用的其他对象也要 clone 一份,这就要求这个被引用的对象必须也要实现 Cloneable 接口并且实现 clone 方法。
- &和&&的区别
(1) &&具有短路的功能,而&不具备短路功能。
(2) 当&运算符两边的表达式的结果都为true时,整个运算结果才为true。而&&运算符第一个表达式为false时,则结果为false,不再计算第二个表达式。
(3) &和&&都可以用作逻辑与的运算符,表达逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false。
(4) &&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式,例如,对于if(str != null && !Str.equals(“”))表达式,当str为null时,后面的表达式不会执行,所以不会出现NullPointerException。如果将&&改为&,则会抛出NullpointerException异常。在if(x==33 & ++y>0)中y会增长;在if(x=33 && ++y>0)中y不会增长
(5) &还可以当做位运算符,当&操作符两边的表达式不刷boolean类型时,&表示按位与操作,我们通常使用
- 两个对象的值相等(x.equals(y)==true),但却有不同的hashCode,这句话对吗?
不对,如果两个对象满足x.equals(y)==true,那么它们的哈希码hashCode应当相同
- 是否可以继承String?
String被设计成final类,不可以被继承。对String类最好的重用方式是关联关系(has-a)和依赖关系(use-a)而不是继承关系(is-a)
- 重载和重写的区别
(1) 两者都是实现多态的方式,重载实现的是编译时的多态,重写实现的是运行时的多态。
(2) 重载发生在同一个类中,重写发生在父类和子类两个类中。
(3) 重载的规则是方法名相同,参数列表不同,与返回值无关。
(4) 重写的规则:方法名相同,参数列表相同;子类返回值类型不大于父类,子类方法声明抛出的异常类不大于父类;子类方法访问权限不小于父类。
- 为什么函数不能根据返回类型来区别重载?
因为调用时不能指定类型信息,编译器不知道你要调用哪个函数。
- char型变量中能不能存储一个中文汉字,为什么?
char类型可以存储一中文汉字,因为java使用的编码是unicode,一个char类型占2个字节(16比特),所以可以存储一个中文汉字。
- 抽象类和接口的区别?什么时候使用抽象类和接口?
(1) 抽象类:
① 可以有构造器、成员变量、静态方法、抽象方法和具体方法
② 类中成员可以是private、default、protected、public
③ 一个类只能继承一个抽象类
④ 含有抽象方法的类一定是抽象类,而抽象类可以没有抽象方法
(2) 接口:
① 不能定义构造器、静态方法
② 方法全是抽象方法
③ 成员全部是public,成员变量实际上都是常量
④ 一个类可以实现多个接口
- 静态变量和实例变量的区别
(1) 静态变量:被static修饰,称为类变量,属于类,通过类名调用,是所有对象所共有的,若一个对象将它的值改变,则其它对象的到的是该便后的结果。一个类不管创建多少个对象,静态变量在内存中有且只有一个拷贝。存储在静态区
(2) 实例变量:必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。属于对象私有的,某个对象将其值改变不会影响其它对象。存储在堆中
- ==和equals的区别
(1) equals:是一个方法,比较两个对象的内容是否相等。不能用于比较基本数据类型,如果没有对其重写,则比较的是引用类型的变量所指向的对象的地址。
(2) == :是一个运算符,用于比较基本数据类型的两个数值是否相等,用于比较引用数据类型的两个地址值是否相等
- Break和continue的区别
(1) Break用于完全结束一个循环
(2) Continue用于跳出本次循环,进入下一次循环
- String s = “Hello”;s = s + “world”;这两行代码执行后,原始的String对象中的内容到底改变了没有?
没有,String 是final类,它的所有对象都是不可变对象,执行String s = “Hello”一句,会在堆中开辟一个内存空间存放“Hello”,s = s + “world”一句执行会在堆中开辟两个空间分别存放“world”和“Hello world”,原始的s所指向的“Hello”从未被改变
- Java中实现多态的机制是什么?
继承、父类的引用指向子类的实例对象、重写
- Java中异常分为哪些种类?
按照异常需要处理的时机分为编译时异常(也叫强制性异常)也叫CheckeException和运行时异常(也叫非强制性异常)也叫RuntimeException
- Error和exception的区别
(1) Error类和exception类的父类都是throwable类
(2) Error类错误是仅靠程序本身无法恢复和预防的,通常是指与虚拟机相关的问题,如系统奔溃,虚拟机错误,内存不足等
(3) Exception类表示程序可以处理的异常,可以捕获并且可能恢复。又可分为运行时异常RuntimeException和受检查时异常CheckedException
- java异常处理机制
Java异常的根类是Throwable,其下面派生两个子类error和exception。Error表示程序本身无法克服和恢复的严重问题;exception表示可能克服和恢复的问题,exception又可分为系统异常和普通异常,系统异常是软件本身缺陷导致的问题,用户无法克服和恢复,但在这种问题下可以让软件继续运行或者直接死掉。而普通异常是运行环境变化导致的问题,用户可以克服和恢复。Java为系统异常和普通异常提供不同的解决方案,编译器强制普通异常必须用try...catch处理或者用throws抛出,所以普通异常有称checked异常;而系统异常可以处理也可以不处理,又可成为unchecked异常
- 请写出你最常见的5个RuntimeException
(1) NullPointerException空指针异常
(2) ClassNotFoundException指定的类找不到
(3) IndexOutOfBoundsException数组下标越界异常
(4) NumberFormatException字符串转换为数字异常
(5) IllegalArgumentWxception 方法传递参数异常
- Throw和throws的区别?
(1) Throw:
用在方法体内、抛出的异常由方法体内的语句来处理、表示抛出一个异常实例、执行throw一定是抛出了某种异常
(2) Throws:
用在方法声明后面、抛出的异常由方法的调用者来处理、表示可能抛出某种类型的异常、throws表示可能抛出某种异常,不一定会发生这种异常
- final、finally、finalize的区别
(1) final:用于声明属性、方法和类时,分别表示属性不可改变,方法不可覆盖,被修饰的类不可被继承
(2) finally:异常处理语句结构的一部分,表示总是执行
(3) finalize:Object类的一个方法,在垃圾回收器执行时会调用被回收对象的此方法进行资源回收。是一个被动方法。该方法被调用表示该对象死亡
- 数组有没有length()方法?String有没有length()方法?
数组没有length()方法,但是有length属性。String有length()方法。JavaScript中,获取字符串的长度可以通过length属性得到。
- String、StringBuilder、Stringbuffer的区别?分别适用于什么场景?
(1) String:只读字符串,String引用的字符串内容不可被改变,底层是字符数组常量,线程安全,效率最慢。
(2) StringBuilder和Stringbuffer表示的字符串对象可以被直接修改。
(3) StringBuffer:多线程,线程安全,效率低
(4) StringBuilder:单线程,线程不安全,效率最高
(5) 使用场景:操作少量数据用String;单线程操作字符串缓冲区下大量数据用StringBuilder;多线程操作字符串缓冲区下操作大量数据用StringBuffer。
- Java的基本数据类型有哪几种?各占几个字节
(1) 四类:整型、浮点型、字符型、布尔型
(2) 八种:整型:byte 1个字节、short 2个字节、int 4个字节、long 8个 字节
(3) 浮点型:float 4个字节、double 8个字节
(4) 字符型:char 2个字节
(5) 布尔型:boolean 1个字节
- int和Integer有什么区别
(1) int是一种基本数据类型,占4个字节;Integer是int的包装类,提供了字符串转换,泛型,自动装箱拆箱等功能
(2) Ingeter变量必须实例化后才能使用,而int变量不需要
(3) int的默认值是0,Integer的默认值是null
(4) 使用框架时最好用Ingeter
- 什么是自动装箱与拆箱?为什么要用自动装箱和拆箱?
(1) 装箱:将基本数据类型用它们对应的引用类型包装起来
(2) 拆箱:将包装类型转换为基本数据类型。
(3) Java使用自动装箱和拆箱机制,节省了常用数值的内存开销,提高了效率,有编译器来完成,编译器会在编译期根据语法决定是否进行撞线和拆箱动作。
- 数据类型之间的转换
(1) 字符串如何转基本数据类型:调用基本数据类型对应包装类中的方法parseXXX(String)或者valueOf(String)
(2) 基本数据类型如何转字符串:一种方法是将基本数据类型与空字符串(“”)连接;另一种方法是调用String类中的valueOf()方法返回相应字符串
- Java中有几种类型的流?
(1) 按流的方向分为输入流和输出流;
(2) 按实现功能为节点流和处理流;
(3) 按处理数据的单位分为字节流和字符流
- 字节流如何转为字符流?
(1) 字节输入流转字符输入流通过InputStreamReader实现;
(2) 字节输出流转字符输出流通过OutputStreamWriter实现。
- 如何将一个java对象序列化到文件里
在java中能够被序列化的类必须先实现Serializable接口。
- 字节流和字符流的区别
(1) 字节流可以处理所有类型数据,处理的单位为一个字节,继承于InputStream、OutputStream;
(2) 字符流只能处理字符数据,处理的单位是2个字节的unicode字符,继承于Reader、Writer
(3) 只要是纯文本数据,就优先考虑使用字符流,除此之外都使用字节流。
- 如何实现对象克隆
(1) 一种方式是实现Cloneable接口并重写Object类中的clone()方法
(2) 另一种方式是实现Serializable接口,通过对象的序列化和反序列化实现深克隆
- 什么是java序列化?如何实现java序列化?
(1) 序列化是一种用来处理对象流的机制,用于解决在对对象流进行读写操作时所引发的问题。
(2) 序列化的实现:需要被序列化的类必须实现serializeable接口
- 请问ArrayList、HashSet、HashMap是线程安全的吗?如果不是那我想要线程安全的集合怎么办
都是线程不安全的,Vector、HashTable倒是线程安全的先要线程安全就在集合的核心方法上添加synchronized关键字
- ArrayList内部是用什么实现的
ArrayList内部是用数组实现的,默认长度是10。线程不安全,效率高,查询快,增删慢。
- List的三个子类的特点
(1) ArrayList底层是数组,查询快,增删慢
(2) LinkedList底层是循环双链表,增删快,查询慢
(3) Vector底层是数组,线程安全,增删慢,查询慢
- List和Map、set的区别
(1) List和set是存储单列数据的集合,map是存储键值对双列数据的集合。
(2) List存储的数据有序可重复的,map存储的数据无顺序,键不可重复,值可重复;set存储的数据是无序不重复的,但位置固定。
- HashMap和HashTable有什么区别
(1) HashMap是线程不安全的,键值不重复但允许空键和空值,效率高。
(2) HashTable线程安全,不允许键值为null
- 数组和链表分别适用于什么情景,为什么?
(1) 数组是连续存储的,查询快,增删慢,适用于数据比较少,经常做的运算是按序号访问元素;
(2) 链表是离散存储的,查询慢,增删快,适用于对线性表的长度或者规模难以估计,频繁做增删操作的;
- Map中的key和value可以为null吗
(1) HashMap对象的key、value值均可以为null;
(2) HashTable对象的key、value值运不可以为null;
(3) 两者的key值均不能重复,若添加key相同的键值对,后面的value会自动覆盖前面的value
- 说说你对java中反射的理解
Java中的反射首先是能够获取到java中要反射类的字节码,获取字节码的方法有:1、Class.forName(className) 2、类名.class 3、this.getClass()。然后将字节码中的方法,变量,构造函数等映射到相应的Method、Filed、Constructor等类,这些类提供了丰富的方法以便我们使用。
- 一个类会在什么时候被初始化
(1) 创建类的实例,也就是new一个对象的时候。。
(2) 访问某个类或接口的静态变量,或者对该静态变量赋值。。
(3) 调用类的静态方法。。
(4) 反射。。
(5) 初始化一个类的子类。。
(6) JVM启动时标明的启动类,即文件名和类名相同的那个类。。
只有以上6种情况才会导致类的初始化!
类的初始化步骤:
1) 如果该类没有被夹在和链接,先进行加载和链接
2) 如果该类存在还没有初始化的直接父类,那就先初始化直接父类
3) 如果该类中存在初始化语句(如static变量和static块),那就先一次执行这些初始化语句。
- 一个“.java”源文件中是否可以包括多个类(不是内部类)?有什么限制?
可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致