Java面向对象基础
-
什么是面向对象编程,Java类和对象有什么区别
OOP(Object Oriented Programming)编程是利用“类”和“对象”来创建模型实现对真实世界的描述
- 使程序更加容易扩展和易修改,使开发效率变得更高。
- 基于面向对象的程序可以使他人更加容易理解你的代码逻辑
类和对象的区别:
- 类是对象的抽象,而对象是类的具体实例;类是现实世界或思维世界中的实体模板,而对象是具体实例
-
OOP的三大特性即核心思想
面向对象的本质是抽象。从面对的问题域抽象出解决问题所需的对象是面向对象方法的核心思想。能否恰当抽象出足够的对象类型,特别是抽象出潜在的对象是决定软件设计好坏的关键。如果从更宽泛的角度讲,对我们所面对的复杂问题进行抽象,抓住本质,得出高度精炼的逻辑模型,对问题的求解具有重要的意义。从这个角度来说,抽象并不仅仅局限于对象的抽象,也包括流程和更高层的系统结构;而封装、继承、多态是面向对象的基本特征
Java的三大特性
-
封装:把客观事物封装成抽象的类, 类可以选择把自己的数据和方法只让可信任的类进行操作, 对不可信的进行隐藏
类 = 数据 + 操作
通过封装, 对象对内部数据和操作进行不同程度的保护, 以防止其他操作意外地改变或错误地使用对象的数据和操作, 发生我们预想之外的非安全操作.
-
继承:通过继承可以使用现有类的所有数据和操作, 并且可以对现有类进行扩展.
被继承的类被称为: 父类 / 基类 / 超类
实现继承的类被称为: 子类 / 派生类*
继承的实现方式有两种:
- 接口继承
接口继承仅使用接口的属性和方法, 但是子类必须提供其具体实现 - 类继承
类继承直接使用现有类的属性和方法而无需提供其具体实现
组合也是继承一种, 但有点不太容易理解.
如果对象的变量或者类变量引用了一个对象, 那么我们也就拥有了该对象对外开放的属性和方法, 也可以说间接的"继承或者说"拥有了"该类的属性和方法. - 接口继承
-
多态:多态是指一个对象的相同方法在不同的情形有不同的表现形式.
多态使得不同内部结构的对象可以共享相同的外部接口.多态的常见表现形式:
- 类实现了接口, 将该类传入接口参数.
- 类继承了父类, 将该类传入父类参数.
很多人认为重载是多态的一种, 但我认为不是, 面向对象的多态是一种运行时的特征, 而不是编译期的特征
-
-
Java抽象类和接口的异同点
-
抽象类:抽象类是用来管理一些抽象内容的类
- 抽象类和抽象方法必须用
abstact
关键字来修饰。 - 抽象方法定义时,只需要声明,不需要实现
- 含抽象方法的类必须被声明为抽象类
- 抽象类的子类必须实现所有的抽象方法后,才能被实例化,若不想实现抽象方法,就定义它为抽象类,否则会报错。
- 不能被实例化
- 抽象类和抽象方法必须用
-
接口:接口(interface)就是定义一套方法/规则,用于对象之间的通信
-
可以定义内部类
-
不能定义变量
-
不能定义代码块
-
不能添加普通/对象/实例方法
-
不能定义构造方法,只有抽象方法,java8后允许接口的默认实现
-
使用implements实现一个接口
-
默认的变量都是static final 常量
-
一个类可以实现多个接口,一个接口可以继承多个接口
-
-
-
JVM,JRE,JDK的区别和关系
JDK(Java Development Kit,Java开发工具包) ,是整个JAVA的核心,包括了Java运行环境JRE(Java Runtime Envirnment),一堆Java工具(javac/java/jdb等)和Java基础的类库
),包含JVM标准实现及Java核心类库。
JRE(Java Runtime Environment Java运行环境) ,是 JDK 的子集,也就是包括 JRE 所有内容,以及开发应用程序所需的编译器和调试器等工具。
JVM(Java Virtual Machine,Java虚拟机), 是JRE的一部分。它是整个Java实现跨平台的最核心的部分,负责解释执行字节码文件,是可运行Java字节码文件的虚拟计算机
-
Java 常用判断 ”==“ 和 ”equals“的区别,从内存的方向解释
- == 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作
- equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断,也可以重写equals方法比较字符是否相等,String类就从写equals方法来实现字符串比较
-
什么是值传递,什么是引用传递
- 值传递: 是指在调用方法时,将实际参数拷贝一份传递给方法,这样在方法中修改形式参数时,不会影响到实际参数。
- 引用传递: 也叫地址传递,是指在调用方法时,将实际参数的地址传递给方法,这样在方法中对形式参数的修改,将影响到实际参数。
- 也就是说值传递,传递的是副本。引用传递,传递的是实际内存地址。这是两者的本质区别
-
什么是深拷贝,什么是浅拷贝,常用的实现方式
-
浅拷贝:浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化
-
深拷贝:深拷贝复制变量值,对于引用数据,则递归至基本类型后,再复制
实现方式:
- 序列化
- 重写对象clone()方法
-
-
Java 常见的四种引用关系即作用范围
-
强引用:类似Object obj = new Object( )这类的引用,只要强引用存在,垃圾收集器永远不会回收掉被引用的对象
-
软引用:描述一些还有用,但并非必需的对象。对于软引用关联的对象,在系统第一次gc时,将会把这些对象列进回收范围之中,以便进行第二次回收,第二次回收的时候就会将软引用关联的对象进行回收。SoftReference类来实现软引用;软引用适合缓存使用的场景
-
弱引用:也是用来描述非必需对象的,但是它的强度比软引用更弱一些。只被弱引用关联的对象,当垃圾收集器工作时,无论当前内存是否足够,都会回收掉被弱引用关联的对象。WeakReference类来实现软引用。
-
虚引用:也称为幽灵引用或者幻影引用,它是最弱的引用关系。无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。PhantomReference类来实现虚引用。
Java堆中保存的直接内存的引用,就是虚引用的使用场景,在垃圾回收虚引用关联的内存的时候,此虚引用关联的直接内存,会收到内存被回收的信息,进而对直接内存进行清理工作
-
-
Java反射机制和语法,泛型和类型擦除的概念
什么是反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
方法名 功能说明 forName(String name) 返回指定类名 name 的 Class 对象 newInstance() 调用缺省构造函数,返回该Class对象的一个实例 newInstance(Object []args) 调用当前格式构造函数,返回该Class对象的一个实例 getName() 返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称 getSuperClass() 返回当前Class对象的父类的Class对象 getInterfaces() 获取当前Class对象的接口 getClassLoader() 返回该类的类加载器 getSuperclass() 返回表示此Class所表示的实体的超类的Class getFields() 获取类中public类型的属性 getField(String name) 获取类特定的方法,name参数指定了属性的名称 getDeclaredFields() 获取类中所有的属性(public、protected、default、private),但不包括继承的属性 getDeclaredField(String name) 获取类特定的方法,name参数指定了属性的名称 getConstructors() 获取类中的公共方法 getConstructor(Class[] params) 获取类的特定构造方法,params参数指定构造方法的参数类型 getDeclaredConstructors() 获取类中所有的构造方法(public、protected、default、private) getDeclaredConstructor(Class[] params) 获取类的特定构造方法,params参数指定构造方法的参数类型 getMethods() 获得类的public类型的方法 getMethod(String name, Class[] params) 获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型 getDeclaredMethods() 获取类中所有的方法(public、protected、default、private) getDeclaredMethod(String name, Class[] params) 获得类的特定方法,name参数指定方法的名字,params参数指定方法的参数类型 泛型信息只存在于代码编译阶段,但是在java的运行期(已经生成字节码文件后)与泛型相关的信息会被擦除掉,专业术语叫做类型擦除
-
Java逃逸分析技术
逃逸分析的基本行为就是分析对象动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他地方中,称为方法逃逸
-
同步省略:在动态编译同步块的时候,JIT编译器可以借助逃逸分析来判断同步块所使用的锁对象是否只能够被一个线程访问而没有被发布到其他线程。
如果同步块所使用的锁对象通过这种分析被证实只能够被一个线程访问,那么JIT编译器在编译这个同步块的时候就会取消对这部分代码的同步。这个取消同步的过程就叫同步省略,也叫锁消除
-
标量替换:在JIT阶段,如果经过逃逸分析,发现一个对象不会被外界访问的话,那么经过JIT优化,就会把这个对象拆解成若干个其中包含的若干个成员变量来代替。这个过程就是标量替换
-
栈上分配:在Java虚拟机中,对象是在Java堆中分配内存的,这是一个普遍的常识。但是,有一种特殊情况,那就是如果经过逃逸分析后发现,一个对象并没有逃逸出方法的话,那么就可能被优化成栈上分配
-
-
Java注解的基本实现,元注解和自定义注解的角度;JDK自带的注解有哪些
-
@Documented:
@Documented 注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中,是一个标记注解,没有成员
-
@Inherited:
@Inherited 用于表示某个被标注的注解是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类
-
@Target:
用于描述注解的范围,即注解在哪用。它说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)等。取值类型(ElementType)有以下几种:
- CONSTRUCTOR:用于描述构造器
- FIELD:用于描述域即类成员变量
- LOCAL_VARIABLE:用于描述局部变量
- METHOD:用于描述方法
- PACKAGE:用于描述包
- PARAMETER:用于描述参数
- TYPE:用于描述类、接口(包括注解类型) 或enum声明
- TYPE_PARAMETER:1.8版本开始,描述类、接口或enum参数的声明
- TYPE_USE:1.8版本开始,描述一种类、接口或enum的使用声明
-
@Retention
用于描述注解的生命周期,表示需要在什么级别保存该注解,即保留的时间长短。取值类型(RetentionPolicy)有以下几种:
- SOURCE:在源文件中有效(即源文件保留)
- CLASS:在class文件中有效(即class保留)
- RUNTIME:在运行时有效(即运行时保留)
-
-
从程序运行的角度解析一个main方法
在JVM实现中,线程为Execution Engine的一个实例,main函数是JVM指令执行的起点,JVM会创建main线程来执行main函数,以触发JVM一系列指令的执行,真正地把JVM run起来。在创建main线程时,会为其分配私有的PC Register、JVM Stack、Native Method Stack,然后进行类加载解析链接等过程