文章目录
- Java 基础
-
- 一、整体观/理论/概念
-
- JDK和JRE的区别
- Java 为什么可以一次编写、到处运行?
- java运行快吗 是编译还是解释型语言
- 什么是API
- import java 和javax的区别
- 重写和重载的区别
- 面向对象和面向过程的区别
- 面向对象的三大特性: 封装 继承 多态
- 向上/向下转型
- 都有常量了为什么还要有枚举?
- 构造器 Constructor 是否可被 override
- 构造方法是什么
- 一个类没有声明构造方法,该程序能正确执行吗
- 构造方法的特性
- 调用子类构造方法之前,会先调用父类无参构造方法,其目的是?
- 在Java中定义一个不做事的构造方法的作用
- 基本数据类型和引用类型的区别
- heap和stack的区别
- Java 反射
- Java的序列化 vs 反序列化
- 什么时候需要序列化
- Java 序列化中如果有些字段不想进行序列化 怎么办
- Java和C++的区别
- 一、对象拷贝
- 二、语法
- 三、Java的数据类型
- 四、字符串:String & StringBuilder & StringBuffer
- 五、抽象类
- 六、集合类
- 七、异常
- 八、JVM
- IO流
- 其他
Java 基础
一、整体观/理论/概念
JDK和JRE的区别
答:jdk是开发工具,给开发者用的;jre是运行时环境,用来运行java程序的;如果你需要编写java程序,需要安装JDK。如果你需要运行java程序,只需要安装JRE就可以了。
JDK包含JRE包含JVM
JDK: Java development kit Java 开发工具
JRE: Java runtime environment Java运行是环境
JDK包含JRE,JRE包含JVM,安装Eclipse你会发现它是运行不起来 是会报错的,只有安装了JDK,配置好了环境变量和path才可以运行成功。
【参考】
Java 为什么可以一次编写、到处运行?
运行过程:Java文件经过编译的.class的字节码文件,Java虚拟机JVM 再把字节码文件翻译成机器码,计算机再执行这个机器码,Java程序就得到运行了。
到处运行:靠的是jvm,不同平台下的jvm是不同的,但他们都能运行这个相同的字节码文件,Java 虚拟机再把这个字节码文件->当前平台下的机器码,java文件就可以实现到处运行。
java运行快吗 是编译还是解释型语言
JVM在执行字节码文件时,是读一行执行一行的,所以是解释型语言;
解释型语言运行得都比较慢。
【参考】
什么是API
其实就是被人写好的可以实现某种特定功能的函数,开发者只需要调用它提供的接口,然后传入它规定的参数,这个函数就会实现相应的功能。
import java 和javax的区别
一开始javax是对JavaAPI的扩展,后来也逐渐把这些扩展移到了java下面,所以现在可以说java包和javax是没有区别的
重写和重载的区别
重写:override 重载:overload
重载: 发生在同一个类中,比如写构造函数的时候一般会写无参构造方法和有参构造方法,方法名必须相同,参数列表不同(类型不同、个数不同、顺序),方法返回值也可以不同。
重写: 发生在父子类中,子类重写父类的方法,方法名、参数列表必须相同(返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类)如果父类
方法访问修饰符为 private 则子类就不能重写该方法。
面向对象和面向过程的区别
- 面向过程:性能比较高,不需要实例化,开销比较小;但没有对象易维护、易复用、易扩展
- 面向对象: 易维护、易复用、易扩展,封装、继承、多态可以降低系统的耦合度,使系统更加灵活、更加易于维护; 性能比面向过程低
面向对象的三大特性: 封装 继承 多态
1. 封装:将类的某些属性、信息封装在类的内部,不允许外部直接访问,而是通过类提供的方法来对类内部的信息进行访问或操作。
2. 继承:子类继承父类,是一种is-a的关系,子类继承到父类属性和方法,在父类基础上进行拓展,添加新的属性和方法,也可以重写父类的方法(父类的private属性和方法、构造方法不能被重写)
has-a:用来判断类与成员的关系,即类拥有某种属性或某种方法
3. 多态:对于同一个方法,不同的参数列表、不同的参数类型传进来可以有不同的处理方式,主要体现在继承和重载
继承:在继承的时候,一个父类可能有多个子类,子类A和子类B都重写了父类的同一个方法,但是子类AB的对象在调用这个方法的时候,都会根据当前子类重写的逻辑来处理,这就是多态。(多态也可以通过接口这种形式实现)
重载:在同一个类里,同一个方法名,不同的参数传进来,会有不同的处理方式,这就是重载;
多态的一种体现就是,你只定义了一个方法和一个参数类型,但却可以处理多种形态的参数,这就是多态。
多态比较难理解
向上/向下转型
向上:将子类对象赋值给父类对象(父类引用指向子类对象),在日常开发中我们大量使用向上转型,这样会充分发挥多态的特性
向下:将父类对象赋值给子类对象,这个是否需要强制类型转换,否则会编译报错(编译通过了也不一定能正确执行)
都有常量了为什么还要有枚举?
关键字:enum,调用时和静态常量一样,它能够更好地限定语义和判断每个值的合理性,它把值限定在了这几个值的范围之内,如果超出了这几个值的范围,在编译的时候就会报错,就能更好地检查每个值的合理性。
构造器 Constructor 是否可被 override
不可以
构造方法是什么
对对象进行初始化
一个类没有声明构造方法,该程序能正确执行吗
可以。会默认执行无参构造方法。
构造方法的特性
1.与类名相同,可以有无参和有参构造方法
2. 没有返回值,但不能用 void 声明构造函数;
3. 生成类的对象时自动执行,无需调用。
调用子类构造方法之前,会先调用父类无参构造方法,其目的是?
帮助子类做初始化工作
在Java中定义一个不做事的构造方法的作用
子类的对象在构造之前,如果没有用 super() 来调用父类特定的构造方法,则会先调用父类的无参构造方法。这个时候,如果父类中没有无参构造方法,那编译就会发生错误。
基本数据类型和引用类型的区别
- 基本:8种
- 引用类型:是指由多个值构成的对象
heap和stack的区别
- heap:堆内存,存对象
- stack:栈内存,存方法内的局部变量
Java 反射
Java的反射是Java能够动态获取信息、动态调用对象方法的一种机制。
在运行状态中,对于任何一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意方法和属性
Java的序列化 vs 反序列化
- 序列化:将java对象转换为字节流的过程
- 反序列化:将字节流转换为java对象的过程
什么时候需要序列化
Java对象在以下情况下需要
- 在网络上传输
- 持久化存储
Java 序列化中如果有些字段不想进行序列化 怎么办
对于不想进行序列化的变量,使用 transient 关键字修饰;
当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复;
transient 只能修饰变量,不能修饰类和方法
Java和C++的区别
同:都是面向对象的语言,都支持封装、继承和多态
异:
- 指针:Java 不提供指针来直接访问内存
- 继承:Java 的类是单继承的,C++ 支持多重继承;虽然 Java 的类不可以多
继承,但是接口可以多继承。 - 内存管理:Java 有自动内存管理机制,不需要程序员手动释放无用内存
一、对象拷贝
什么是克隆
对数据进行拷贝
如何实现对象克隆
实现Clonable接口,实现clone()方法
深拷贝 vs 浅拷贝
- 浅拷贝:只拷贝对象本身,不拷贝对象的引用
- 深拷贝:对象本身+引用
二、语法
引用传递和值传递
Java只有值传递,
实参:要传递给方法的实际参数,在方法外面
形参:方法名的参数列表,在方法里面
值传递:对形参的修改不会影响到实参的值
引用传递:对形参的修改会影响到实参的值
JVM中划分了好几块内存区域,其中有一个栈空间和一个堆空间,创建的所有对象存放在堆中,基本数据类型和局部变量是存放在栈中的。
当操作对象时,对象是存放在堆中的,我们拿到的只是这个对象的引用,通过对象的引用,就可以操作对象;如果是基本数据类型,那就复制一份值,传递给形参;如果是引用类型,那就将引用赋值一份传递给形参,形参拿到的始终是一个副本,无论如何都无法通过形参改变实参,毕竟形参只是操作的副本而已
为什么Java只有值传递
概念:值传递:对形参的修改不会影响到实参的值;引用传递:对形参的修改会影响到实参的值
原因:实参传递给形参时,形参拿到的始终都是一个副本而不是实参本身,所以无论形参怎么改变都不会影响到实参的值,所以是Java只有值传递
== 和equals的区别
都用用来判断相等的
“==”:判断两个对象的地址是否相等
equals:永远都是比较内容。默认执行 = =;如果重写了就是比较对象的内容,String重写了equals,所以String在用equals的时候比较的是内容。
对象的相等 vs 指向他们的引用相等
- 对象的相等:比较的是内容
- 引用相等:在内存中的地址
两个对象hashCode()相同,equals()一定为true吗
不一定。
hashCode:获取哈希码,由哈希码来确定对象在哈希表中的索引位置(Java的任何类都有hashCode函数)
equals是比较两个对象是否想等的,hashCode相同只能说明它们的哈希码相同,被散列到相同的索引位置,但并不能说明两个对象相等。
排序
Collections.sort 和 Arrays.sort的区别
- Collections.sort默认调用Arrays.sort方法,底层实现都是TimSort实现的(这是jdk1.7新增的,以前是归并排序)
- TimSort算法:对于没有排好序的部分进行排序,然后再合并(就是找到已经排好序数据的子序列,然后对剩余部分排序,然后合并起来)
final
1)变量:
1)基本数据类型:数值初始化了之后不能被修改;
2)引用类型:初始化之后就不能再指向其他对象了
2)类:不可派生类,不能再被继承,final类中的所有成员方法也都被隐式地指定为final方法
3)方法:方法锁定,对于方法所在的类,它的子类是不能够修改这个方法(所有private方法都隐式地指定为final)
不能修饰接口和抽象类 interface abstractClass
static
将类的成员属性和成员变量定义为static时,就意味着将他们声明为静态属性和静态方法,,不用创建对象,直接通过类名就可以调用。
只能修饰变量和方法,被static修饰的成员随着类的加载而加载,生命周期和类一样;
没有被static修饰的变量和方法只能通过创建对象的形式调用(new 类名.方法名的方式),只能以对象的形式存在,被static修饰的成员是优先于对象存在的,静态的方法在调用非静态的成员时,非静态的成员还没有存在,所以不能调用非静态的变量或方法
在一个静态方法内调用一个非静态成员为什么是非法的
由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非
静态变量,也不可以访问非静态变量成员。
静态方法和实例方法的区别
- 调用:调用静态方法需要创建对象,用“类名.方法名”的方式;实例方法不需要创建对象
- 静态方法只能访问静态成员变量和静态方法;实例方法则没有限制
内部类
在一个类中定义的类就是内部类,不同的内部类其实就是作用范围不一样
public:类在本程序的任何地方都能使用,不加则代表这个类只能在所处的包下访问,
成员变量和局部变量的区别
概念:成员变量是类的成员变量,局部变量是方法内的局部变量
- 内存:成员变量是对象的一部分,跟对象一起保存在堆中;局部变量保存在栈中
- 生存时间:成员变量是对象的一部分,它随着对象的创建而存在;局部变量在方法调用完毕后会消失
- 赋值:成员变量如果没有被赋初值,则会自动以类型的默认值而赋值;而局部变量则不
会自动赋值。
如何创建对象
new
对象实体与对象引用的区别
- 对象实体:new了之后存放在堆中的,可以n个引用指向它
- 对象引用:存放在栈中的,是指向某个对象的(指向0或1个对象)
返回值在类的方法里的作用
方法的返回值:执行某个方法后返回的数据
返回值的作用:用于接收某个过程的结果,这个结果可能会被用于其他操作
Stream
2.32 Stream有哪些方法
Stream提供了大量的方法进行聚集操作,
中间方法:中间操作允许流保持打开状态,并允许直接调用后续方法。
- mapToInt(),boxed()
末端方法:末端方法是对流的最终操作。当对某个Stream执行末端方法后,该流将会被“消耗”且不再可用。 - toArray(),forEach()
在数组和list做转换的时候,就会用到strem
Math函数常用的方法
min()max()abs()round()pow()exp()
round():round(-1.5)等于多少——-1
- 正数:正常的四舍五入,到5了就会进一
- 负数:到5了不会进一,超过5了才会进一
【