![cf241f848166dda184eece72b5d313c1.png](https://img-blog.csdnimg.cn/img_convert/cf241f848166dda184eece72b5d313c1.png)
1、Java特性、原则、设计模式
Java三大特性:
封装、继承、多态。
面向对象的四大特征:
封装、继承、多态、抽象。
面向对象7大设计原则:
- 单一职责原则——SRP
让每个类只专心处理自己的方法。
- 开闭原则——OCP
软件中的对象(类,模块,函数等)应该对于扩展是开放的,但是对于修改是关闭的。
- 里式替换原则——LSP
子类可以去扩展父类,但是不能改变父类原有的功能。
- 依赖倒置原则——DIP
应该通过调用接口或抽象类(比较高层),而不是调用实现类(细节)。
- 接口隔离原则——ISP
把接口分成满足依赖关系的最小接口,实现类中不能有不需要的方法。
- 迪米特原则——LOD
高内聚,低耦合。
面向对象的23种设计模式:
常见的有 抽象工厂模式、工厂方法模式、建造者模式、单例模式。
![d0b77d215465d6ea1cbc57bfe7fa5795.png](https://img-blog.csdnimg.cn/img_convert/d0b77d215465d6ea1cbc57bfe7fa5795.png)
2、8种基本数据类型
String不是基本类型。
双等号(==),比较的是他们的值。基本数据类型没有equals方法。
![0ade7045af2612735923497d53833b6e.png](https://img-blog.csdnimg.cn/img_convert/0ade7045af2612735923497d53833b6e.png)
拆箱和装箱:
//自动装箱
Integer total = 99;
//自定拆箱
int totalprim = total;
Integer i = 400;
Integer j = 400;
System.out.println(i==j); //false
- 使用Integer去创建一个数,虚拟机自动为代码做了这个操作 Integer.valueOf(),源码如下:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
如果值的范围在-128到127之间,它就从高速缓存返回实例。否则 new 一个Integer对象。new Integer 就是一个装箱的过程了,装箱的过程会创建对应的对象,这个会消耗内存,所以装箱的过程会增加内存的消耗,影响性能。
Integer和int 的区别:
int是java的原始数据类型,Integer是java为int提供的封类。
Integer的默认值是null;int的默认值是0。
总结:
- 两个通过new生成的Integer变量永远是不相等的。因为new生成的是两个对象,其内存地址不同。
- Integer与new Integer不会相等。因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同。
- 两个都是非new出来的Integer,(即Integer total = 99 这种 )如果数在-128到127之间,则是true,否则为false。
- Integer变量和int变量比较时,只要两个变量的值是相等的,则结果为true。(因为包装类Integer和基本数据类型int比较时,java会自动拆箱为int,然后进行比较,实际上就变为两个int变量的比较)
3、访问修饰符
![2d9fd5ab7a6198f53ee9a8c215d18735.png](https://img-blog.csdnimg.cn/img_convert/2d9fd5ab7a6198f53ee9a8c215d18735.png)
public:所有地方的类都可以访问。 private:只能在当前类中进行访问。 protected:可以在当前类、当前包、子类中进行访问 不写默认为default:可以在当前类,当前包中进行访问。
4、==、equals、hashcode区别
- ==比较的是两个引用在内存中指向的是不是同一对象(即同一内存空间)
- equals用来比较 两个对象的内容(值)是否相等。
基本数据类型==比较都是值。
有没有可能两个不相等的对象有相同的hashcode?
有可能。称为hash冲突。
总结
(1) 同一对象上多次调用hashCode()方法,总是返回相同的整型值。
(2) 如果a.equals(b),则一定有a.hashCode() 一定等于 b.hashCode()
(3)如果!a.equals(b),则a.hashCode() 不一定等于 b.hashCode()。此时如果a.hashCode() 总是不等于 b.hashCode(),会提高hashtables的性能。
(4)a.hashCode()==b.hashCode() 则 a.equals(b)可真可假。
(5)a.hashCode()!= b.hashCode() 则 a.equals(b)一定为假。
5、重载(Overload)和重写(Override)的区别
方法的重载和重写都是实现多态的方式,区别在于:
重载实现的是编译时的多态性。 重写实现的是运行时的多态性。
- 重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重载对返回类型没有特殊的要求,不能根据返回类型进行区分。
- 重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。
6、抽象类和接口的区别
抽象类特点:
- 抽象类是抽象的,不是具体的,所以抽象类不能被实例化。但是它仍然具有类的功能,成员变量、成员方法和构造方法的访问方式和普通类一样,也可以实现接口、继承类。
- 由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。所以,类的声明、方法体 就不能使用
final
去修饰,final表示不可继承和修改,但是变量可以使用final修饰。 - 抽象类可以有非抽象方法。
- 抽象类中的抽象方法的访问类型可以是public,protected和默认类型。
public abstract class Employee extends Person implements People{
{
public final String a ="1";
static {
System.out.println("我是抽象类的static代码块");
}
public static void test(){
System.out.println("我是抽象类的static方法");
}
public abstract void abstrartMethod();
public void abstrartMethod2() {
System.out.println("抽象类也可以拥有非抽象方法");
}
}
接口的特点:
- 接口中方法默认是
public abstract
(只能是这两个关键字,或其中一个或都省略)。因为要被继承,所以是public的。 - 接口中的变量默认是
public static final
(只能是这三个关键字,或其中两个/一个或都省略)。接口中有成员变量意义不大,实现类可以通过接口名称.变量名称
来调用。 - java中一个类只能继承一个类,但一个接口可以继承多个接口。
- 接口不能实现接口
- 接口中不能有构造方法。
- 1.8中及以后,接口中可以有default默认方法(普通方法),可以有静态方法和方法体了。
public interface People {
public static String a ="1";
public static final String b ="2";
public static void test(){
System.out.println("我是接口的静态方法");
}
//普通方法
default void testA2() {
System.out.println("A");
}
public void test1();
}
7、&和&&的区别
&是位运算符,表示按位 与运算。(两个操作数中位都为1,结果才为1,否则结果为0)
&&是逻辑运算符,表示逻辑与(and)。
8、switch中能否使用string做参数?
在JDK 1.7之前,switch只能支持byte,short,char,int或者其对应的包装类以及Enum类型.从JDK 1.7之后switch开始支持String类型.但到目前为止,switch都不支持long类型。
还有break的坑:
只要没有break ,就一直往下渗透,包括default。
public class SwitchCaseTest {
public static void main(String[] args) {
int num = 2;
switch (num) {
case 1:
num++;
case 2:
num++;
case 3:
num++;
default:
num++;
break;
}
System.out.println(num); //5
}
}
9、String、StringBuffer、StringBuilder区别
- 可变性 简单的来说:String 类中使用 final 关键字字符数组保存字符串,
private final char value[]
,所以 String 对象是不可变的。而StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串char[] value
但是没有用 final 关键字修饰,所以这两种对象都是可变的。 - 安全性
String 是一个字符串常量,final修饰,当创建之后即不能更改,不可被继承,线程安全
StringBuilder 用了synchronized
修饰,线程安全,StringBuffer 线程不安全
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
- 效率
StringBuffer很多方法都加了 synchronized , 也就是同时刻只能有一个线程去执行一个方法 ,效率就低。
对于三者使用的总结:
- 操作少量的数据 = String
- 单线程操作字符串缓冲区下操作大量数据 = StringBuilder
- 多线程操作字符串缓冲区下操作大量数据 = StringBuffer
留个题目:
public class Test {
public static void main(String[] args) {
StringBuffer a = new StringBuffer("A");
StringBuffer b = new StringBuffer("B");
operator(a, b);
System.out.println(a + "," + b);
}
public static void operator(StringBuffer x, StringBuffer y) {
x.append(y); y = x;
}
}
输出是 AB,B
10、Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?
Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。
四舍五入的原理是在参数上加0.5然后进行下取整。