面向对象的特征:
封装,继承,多态和抽象
封装
封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而言它的内部细节是隐藏的,暴露给外界的只是它的访问方法。封装给对象提供了隐藏内部特性和行为的能力。对象提供一些能被其他对象访问的方法来改 变它内部的数据。
在 Java 当中,有 3 种修饰符: public、private、 protected(继承权限,是包权限的扩展,子女类也可使用) 和不写默认 friendly(包权限) 。每一种修饰符 给其他的位于同一个包或者不同包下面对象赋予了不同的访问权限。 下面列出了使用封装的一些好处:
-
通过隐藏对象的属性来保护对象内部的状态。
比如:有一个员工类(employee),员工的身份证号是保密的,不对外提供。这时候就可以私有化属性,并且不对外提供 get()方法。
-
提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩展。
比如:有一个员工类(employee),原有类中 age 属性是 int 型,我现在想把 age 改成 String 类型。如果没有该类没有封装,就会导致,每一处调用到该类的代码都需要修改。但是如果封装了,只需要修改封装类中的 age 属性的类型即可,其他各处使用 employee.setAge(27) 即可。
-
禁止对象之间的不良交互提高模块化,可以对成员变量进行更精确的控制。 比如,set employee 类中员工的 age 属性值,一不小心设置成了 270。为了避免这种错误,可以在 set 方法中控制。
继承
继承给对象提供了从基类获取字段和方法的能力。继承提供了代码的重用行,也可以在不修改类的情况下给现存的类添加新特性。
多态
多态是编程语言给不同的底层数据类型做相同的接口展示的一种能力。一个多态类型上的操作可以应用到其他类型的值上面。 简单来说就是同一个行为,具有多种不同的表现形式或形态的能力。同一个接口,使用不同的实例,执行不同的操作。(继承,重写,父类引用指向子类对象)
--- 重写(Override)
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
--- 重载(Overload)
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
抽象
抽象是把想法从具体的实例中分离出来的步骤,因此,要根据他们的功能而不是实现细节来创建类。 Java 支持创建只暴漏接口而不包含方法实现的抽象的类。这种抽象技术的主要目的是把类的行为和实现细节分离开。
常见的Java问题
1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?
Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。
Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。
2.JDK和JRE的区别是什么?
Java 运行时环境(JRE)是将要执行 Java 程序的 Java 虚拟机。它同时也包含了执行 applet 需要的浏览器插件。
Java 开发工具包(JDK)是完整的 Java 软件开发包,包含了 JRE,编译器和其他的工具(比如:JavaDoc,Java 调试器),可以让开发者开发、编译、执行Java应用程序。
3.”static”关键字是什么意思?Java中是否可以覆盖(override)一个 private 或者是 static 的方法?
static 主要作用就是方便在没有创建对象的情况下来进行调用成员方法或成员变量。
Java 中 static 方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static 方法跟类的任何实例都不相关,所以概念上不适用。 private 为私有属性,所以不能被覆盖。
static 可以用来修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能。
3.1)static 方法:
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有 this 的,因为它不依附于任何对象,既然都没有对象,就谈不上 this 了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
3.2)static变量
static 变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static成员变量的初始化顺序按照定义的顺序进行初始化
3.3)static代码块
static 关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static 块可以置于类中的任何地方,类中可以有多个 static 块。在类初次被加载的时候,会按照 static 块的顺序来执行每个 static 块,并且只会执行一次。 作用:用于给类初始化(有的类不用构造函数,而需要初始化)
3.4.static能作用于局部变量么?
在C/C++中 static 是可以作用域局部变量的,但是在Java中切记:static是不允许用来修饰局部变量。不要问为什么,这是Java语法的规定。
4.集合
4.1)Java 集合框架
在JAVA的util包中有两个所有集合的父接口 Collection 和 Map, 它们的父子关系:

4.2)那么为什么要分为 Collection 和 Map 两种集合?
1.容器内每个位置所存储的元素个数不同。
Collection 类型者,每个位置只有一个元素。用于存放一堆/组数据。
Map 类型者,持有 key-value pair,像个小型数据库。用来存放关系型数据。
4.2.1)那么 Collection 接口下为什么又分为 List 和 Set 两种接口?
List:用来处理序列的。对于存放的元素是有序(存放顺序)的并且可以重复。
Set:用来处理集合的。对于存放的元素是无序(存放顺序)的并且不可以重复,重复的数据将被覆盖掉。(注意:元素虽然无放入顺序,但是元素在 set 中的位置是有该元素的 HashCode 决定的,其位置其实是固定的,加入 Set 的 Object 必须定义 equals() 方法 ,另外 list 支持 for 循环,也就是通过下标来遍历,也可以用迭代器,但是 set 只能用迭代,因为他无序,无法用下标来取得想要的值。)
4.2.1.1)那么 List 接口下为什么又分为 ArrayList 、LinkedList 和 Vector 三种类?
1.底层实现方式:
ArrayList 和 Vector 的底层是数组。每个索引的位置是实际的数据,我们可以按位置索引号取出某个元素,允许元素重复和为null。
LinkedList 的底层是双向链表。而LinkedList中的每个节点中存储的是实际的数据和前后节点的位置。
2.性能
ArrayList 它支持以角标位置进行索引出对应的元素(随机访问),而 LinkedList 则需要遍历整个链表来获取对应的元素。因此一般来说 ArrayList 的访问速度是要比 LinkedList 要快的。
ArrayList 由于是数组,对于删除和修改而言消耗是比较大(复制和移动数组实现), LinkedList 是双向链表删除和修改只需要修改对应的指针即可,消耗是很小的。因此一般来说 LinkedList 的增删速度是要比 ArrayList 要快的
Vector 和 ArrayList 底层都是由数组实现的。但是由于 Vector 的方法加了synchronized, 而 ArrayList 则没有。Vector 属于线程安全级别的,但是大多数情况下不使用 Vector,因为线程安全需要更大的系统开销
4.2.1.2)那么 Set 接口下为什么又分为 HashSet 和 TreeSet 两种类?
1. 底层存储的数据结构不同
HashSet 底层用的是 HashMap 哈希表结构存储
TreeSet 底层用的是 TreeMap 树结构存储
2.存储时保证数据唯一性依据不同
HashSet 是通过复写 hashCode() 方法和 equals() 方法来保证的
HashSet 是通过 Compareable 接口的 compareTo() 方法来保证的
3.有序性不一样
HashSet无序。
TreeSet有序 (这里的有序不是指存放顺序,而是排序算法), TreeSet 存储对象的时候, 可以排序, 但是需要指定排序的算法(自然排序或定制排序)。比如在存储 Integer 能排序(有默认顺序), String 能排序(有默认顺序), 自定义的类存储的时候出现异常(没有顺序)。
TreeSet 判断两个对象不相等的方式是两个对象通过 equals 方法返回 false,或者通过 CompareTo 方法比较没有返回 0