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方法比较得是对象得值
hashCode() 的作用
- 获取哈希码,也称散列码;它实际上返回的是一个int整数。这个哈希码的作用是确定对象在该哈希表中的索引位置。
散列表指的是java集合中本质是散列表的类hashMap,hashTable,hashSet
hashCode() 在散列表中才有用,在其它情况下没用。
在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
hashCode与equals(重要)
- 如果两个对象相等,则hashCode一定也是相同的。
- 两个对象相等,对两个对象分别调用equals方法都返回true。
- 两个对象有相同的hashCode值,它们也不一定是相等的。
- 因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖。
- hashCode() 的默认行为是对堆上的对象产生独特值。
- 如果没有重写hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)
原文
https://segmentfault.com/a/1190000020522150