Java 基础
自己临时整理存储
面向对象的特征?
- 封装:将对象不需要让外界访问的成员变量和方法私有化,只提供公有方法访问。
- 继承:从父类继承信息创建子类。(子类继承父类所有属性和方法,但是私有属性和方法子类是无法访问的,只是拥有。子类可以拥有自己的属性和方法,子类可以以自己的方式实现父类的方法(重写))
java 是值传递的
基本数据类型传递的是值的 copy,引用类型传递的是地址值的 copy。
- 基本类型的传递:方法只是得到了拥有相同值的新变量,只能修改新变量的值,不影响原先的变量。
- 引用类型的传递:方法得到了拥有相同地址值得新对象,可以修改对象的值。
- 引用类型的传递:不能让原先的对象引用新的地址值。
构造方法有哪些特性?
- 名字与类相同。
- 没有返回值,但也不能用 void 声明构造函数。
- 生成类的对象时自动执行,无需调用。
构造器 Constructor 是否可以被 override?
- 父类私有属性和构造方法并不能被继承,所以 Constructor 也就不能被 override(重写),但是可以 overload(重载),所以你可以看到一个类中有多个构造函数的情况。
java 中的无参构造方法的作用?
- 对该类成员进行初始化操作。
- 在程序执行子类构造方法之前,如果没用 super() 来调用父类特定的构造方法,则会调用父类无参构造方法。
调用子类构造方法前会先调用父类构造方法,目的是什么?
- 对继承自父类的成员初始化操作。
重载和重写的区别?
- 重载:发生在同一个类中,方法名必须相同,参数类型不同,个数不同,顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。
- 重写:发生在父子类中,方法名,参数列表必须相同,返回值范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。
什么自动拆箱和自动装箱?
- 装箱:将基本类型用它们对应的引用类型包装起来。(包装类型引用指向基本类型)
- 拆箱:将包装类型转换为基本数据类型。(基本类型引用指向包装类型)
接口和抽象类的区别是什么?
- 接口的默认方法是 public,所有方法在接口中不能有实现(java8 开始接口方法可以有默认实现),而抽象类可以有非抽象方法。
- 接口中除了 static,final 变量,不能有其他变量,而抽象类不一定。
- 一个类可以实现多个接口,但只能实现一个抽象类。接口自己本身可以通过继承(extends)拓展多个接口。
- 接口方法默认修饰符是 public,而抽象方法可以有 public,protected 和 default 这些修饰符(抽象方法就是为了被重写所有不能使用 private 关键字修饰)
- 从设计层面来说,抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为规范。
在 jdk1.8 中,接口也可以定义为静态方法,可以直接用接口名调用。实现类和实现是不可以调用的。如果同时实现两个接口,接口中定义了一样的默认方法,则必须重写,不然会报错。
成员变量与局部变量的区别有哪些?
- 成员变量属于类,局部变量是方法的参数和变量。成员变量可以用 public,private,static 等修饰符修饰,局部变量则不能,但他们都能被 final 修饰。
- 从变量在内存中的存储方式来看,static 修饰的成员变量是属于类的。如果没有 static 修饰,那这个变量是属于实例的。对象存在于堆内存,局部变量则存在于栈内存。
- 成员变量是对象的一部分,随着对象的创建而创建,而局部变量随着方法调用而自动消失。
- 成员变量变量如果没有被赋初值;则会以类型的默认值而复制。(被 final 修饰的成员变量也必须显式的赋值),而局部变量则不会自动赋值。
对象的相等和引用的相等,两者有什么不同?
- 对象的相等比较的是内存中的内容是否相等。而引用相等,比较的是他们指向的内存地址是否相等。
静态方法和实例方法有何不同?
- 调用静态方法无需创建对象,可以直接用类名和对象调用。
- 静态方法访问本类的成员时,只允许访问静态成员(静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。
静态方法里调用非静态成员为什么是非法的?
- 由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。
什么是方法返回值,返回值在类的方法里的作用是什么?
- 方法的返回值是指我们获取到的某个方法体中的代码执行结果!
- 返回值的作用:接收出结果,使它可以用于其他的操作!
创建一个对象用什么运算符?对象实体与对象引用有何不同?
- new 运算符,new 创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用放在栈内存中)。
一个对象引用可以指向 0 个或 1 个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有 n 个引用指向它(可以用 n 条绳子系住一个气球)
关于 final 关键字的一些总计
final 关键字主要用在三个地方:变量、方法、类。
- 被 final 修饰变量,基本数据一旦初始化不能更改、引用类型初始化后不能指向另一个对象。
- 被 final 修饰的类,不能被继承,所以的成员方法都被隐式的指定为 final 方法。
-
使用 final 的原因:
- 第一个原因是把方法锁定,以防止任何继承类修改它的含义;
- 第二个原因是效率。在早期的 java 实现版本中,会将 final 方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升(现在的 java 版本已经不需要使用 final 方法进行这些优化了)类中所以的 private 方法都隐式的制定为 final。
super 关键字总结
- 访问父类的构造函数:可以使用 super() 函数访问父类的构造函数,从而委托父类完成一些初始化的工作。
- 访问父类的成员:如果子类重写了父类的中某个方法的实现,可以通过使用 super 关键字来引用父类的方法实现。
String 为什么是不可变的?
String 使用 final 关键字修饰字符数组来保存字符串,所以是不可变可变的。
-
好处:
- 常量是线程安全的。
- 不可变的特性作为 hashMap 的 key 使得 hash 值也不可变,只需要计算一次。
- StringPool 常量池的需要,重复引用。
-
坏处:
- 修改 String 值会重新创建新的常量或对象,而不是修改原有的值。
StringBuilder 和 StringBuffer 的区别是什么?
-
相同:
- 都是可变的。
- 初识容量都是 16 个字符,当该对象的实体存放的字符长度大于 16 时,实体容量就自动增加。
- 尝试将新容量扩为大小变成原容量的 1 倍 +2,然后 if 判断一下 容量如果不够,直接扩充到需要的容量大小。
-
不同:
- StringBuffer 是线程安全的,内部使用 synchronized 进行同步。
- StringBuilder 是线程不安全的。
== 和 equals(重要)
- == 基本类型比较的是值,引用类型比较的是地址值。
- equals(); 它的作用也是判断两个对象是否相等。
-
但它一般有两种使用情况:
- 类没有覆盖 equals 方法,则 equals 等价于 ==
- 覆盖 equals 方法,比较对象时,若他们内容相等,则返回 true
String 中的 equals 方法是被重写过的,因为 object 方法的 equals 方法比较的对象内存地址,而 string 得 equals 方法比较得是对象得值
(当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。)
hashCode() 的作用
- 获取哈希码,也称散列码;它实际上返回的是一个 int 整数。这个哈希码的作用是确定对象在该哈希表中的索引位置。
散列表指的是 java 集合中本质是散列表的类 hashMap,hashTable,hashSet
hashCode() 在散列表中才有用,在其它情况下没用。
在散列表中 hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
hashCode 与 equals(重要)
- 如果两个对象相等,则 hashCode 一定也是相同的。
- 两个对象相等, 对两个对象分别调用 equals 方法都返回 true。
- 两个对象有相同的 hashCode 值,它们也不一定是相等的。
- 因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖。
- hashCode() 的默认行为是对堆上的对象产生独特值。
- 如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)