目录
- 背景
- 步骤
- 宏观
- 微观
- 理论
- 基础用法
- 面向对象
- 数据类型
- 基础语法(关于方法)
- try(正常的逻辑代码)
- catch(这个和异常有关系)
- finally(经典面试题)
- 高阶使用
- 序列化
- 泛型
- 注解
- 反射
- 总结
背景
后端离不开java,java离不开javase,让我们来总结一下这些零散技术之间的关系吧。
步骤
宏观
学习一个新东西,要从理论和实践两方面进行学习,理论学习包括但不限于5w2h,这些知识又分为使用频率高的和使用频率低的,频率低的并不代表不重要,如自定义注解,反射等,这些往往蕴含着较为深刻的思想。
微观
理论
从三个方面来回答理论的问题,那就是为什么,是什么,特点。
一个东西的出现一定有他的原因,如面向对象语言是为何过渡到面向对象语言java的
1、技术进步的推动:这种成本的下降不仅使得台式电脑等硬件设备的价格更加亲民,也促使了计算机硬件性能的普遍提升。这为软件开发提供了更强大的硬件支持,使得复杂的面向对象编程成为可能。
编程需求的变化:随着硬件性能的提升,软件规模和复杂度也随之增长。传统的面向过程编程在面对大规模、复杂的系统时,存在着重用性、可维护性和可扩展性等方面的问题。而面向对象编程通过将对象作为程序的基本单元,将数据和操作封装在一起,使得程序结构更加清晰、易于维护,同时也提高了代码的重用性。
编程效率的提升:面向对象编程强调代码的重用和封装,这有助于减少开发人员在编写新代码时的工作量。同时,由于面向对象编程更加贴近现实世界的思维模式,使得开发人员能够更加直观地理解和设计程序,从而提高了编程效率。
说到java就离不开java的特性:
面向对象,平台无关性,支持多线程,编译和解释并存。
JVM:Java Virtual Machine,Java 虚拟机,Java 程序运行在 Java 虚拟机上。针对不同系统的实现(Windows,Linux,macOS)不同的 JVM,因此 Java 语言可以实现跨平台。
JRE: Java 运⾏时环境。它是运⾏已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机(JVM),Java 类库,Java 命令和其他的⼀些基础构件。但是,它不能⽤于创建新程序。
JDK: Java Development Kit,它是功能⻬全的 Java SDK。它拥有 JRE 所拥有的⼀切,还有编译器(javac)和⼯具(如 javadoc 和 jdb)。它能够创建和编译程序。
那jvm是干嘛的
Java 程序是通过 Java 虚拟机在系统平台上运行的,只要该系统可以安装相应的 Java 虚拟机,该系统就可以运行 java 程序。从而实现跨平台性。
Java 程序从源代码到运行主要有三步:
编译:将我们的代码(.java)编译成虚拟机可以识别理解的字节码(.class)
解释:虚拟机执行 Java 字节码,将字节码翻译成机器能识别的机器码
执行:对应的机器执行二进制机器码
基础用法
面向对象
首先这个图分为三部分,面向对象是什么,使用什么样的形式保证写出来的代码一定是面向对象的,以及涉及到的一些常见问题。
面向对象是什么
面向对象是相对于面向过程来讲的,面向对象方法,把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。
具体执行的时候:
把构成问题的事务分解成各个对象,而建立对象的目的也不是为了完成一个个步骤,而是为了描述某个事件在解决整个问题的过程所发生的行为。 目的是为了写出通用的代码,加强代码的重用,屏蔽差异性。
三大特性
说到面向对象,保证咱们写出来的代码是符合面向喜爱你个思想的话就要符合封装继承多态。
目的是复用扩充维护。
封装继承多态
封装:封装是把一个对象的属性私有化,同时提供一些可以被外界访问的方法。
继承:继承允许一个类(子类)继承现有类(父类或者基类)的属性和方法。以提高代码的复用性,建立类之间的层次关系。
多态(代码更加灵活,运行的时候才知道真正调用的对象是谁):
多态允许不同类的对象对同一消息做出响应,但表现出不同的行为(即方法的多样性)。
子类继承父类
子类重写父类的方法
父类引用指向子类的对象
对象
上边讲了“面向”对象,下边的重点就是对象,在使用对象的时候会出现什么问题呢,如
equals 和 == 之间的关系是什么???
== :它的作⽤是判断两个对象的地址是不是相等。即,判断两个对象是不是同⼀个对象(基本数据类型
比较的是值,引⽤数据类型 == 比较的是内存地址)。
equals() : 它的作⽤也是判断两个对象是否相等。但是这个“相等”一般也分两种情况:
默认情况:类没有覆盖 equals() ⽅法。则通过 equals() 比较该类的两个对象时,等价于通过“ == ”比较这两个对象,还是相当于比较内存地址。
hashCode 与 equals?
hashCode 方法主要用来获取对象的哈希码,哈希码是由对象的内存地址或者对象的属性计算出来的,它是⼀个 int 类型的整数,通常是不会重复的,因此可以用来作为键值对的建,以提高查询效率。
为什么重写 quals 时必须重写 hashCode ⽅法?
如果重写了 equals()方法而没有重写 hashCode()方法,那么被认为相等的对象可能会有不同的哈希码,从而导致无法在集合中正确处理这些对象。
Java 是值传递,还是引用传递?
深拷贝和浅拷贝
数据类型
现在还在基础使用这一块,基础使用是要明确java是面向对象语言以后,主要分为属性和方法,属性部分一定离不开的是数据类型,数据类型分为基本数据类型和引用类型。学完单个的数据类型以后,我们需要关注类型转换的变化。
基本数据类型
首先说什么是数据类型,根据人们的需求对数据进行分类,主要分为三类,数值,字符,布尔。
数值分为整型和浮点型 ,字符只有char类型 ,布尔型只有两种情况。
这里涉及到一个精度和大小的问题
引用数据类型
这里重点讲解String 类型和Intrger类型
String
Java 中的基本数据类型只有 8 个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(reference type)。
String 是一个比较特殊的引用数据类型。
String 类使用 final 修饰,是所谓的不可变类,无法被继承。
String 和 StringBuilder、StringBuffer 之间的区别是什么
共同点:
都是用于处理字符串的
不同点:
String类的对象是不可变的,每次添加都会有新的对象出来。
StringBuilder 不是线程安全的,添加是在原基础上进行的添加修改。
StringBuffer和StringBuilder类似,但StringBuffer是线程安全的,方法前面都加了synchronized关键字。
String str1 = new String(“abc”)和 String str2 = “abc” 和 区别?
当字符创常量池没有 “abc”,此时会创建如下两个对象:
一个是字符串字面量 “abc” 所对应的、字符串常量池中的实例
另一个是通过 new String() 创建并初始化的,内容与"abc"相同的实例,在堆中。
Integer
Intrger缓存问题
Integer a= 127,Integer b = 127;Integer c= 128,Integer d = 128;相等吗?
要解决这个问题就要先解决一个别的问题:为什么有Integer缓存?什么是 Integer 缓存?
根据实践发现,大部分的数据操作都集中在值比较小的范围,因此 Integer 搞了个缓存池,默认范围是 -128 到 127。
所以才有了上边的127 和 128 的问题,上边这个概念其实也涉及到装箱拆箱的概念。
Integer a = 127;
Integer b = 127;
Integer.valueOf()方法会针对数值在-128 到 127 之间的Integer对象使用缓存。因此,a和b实际上引用了常量池中相同的Integer对象。
Integer c = 128;
Integer d = 128;
c和d不相等。这是因为 128 超出了Integer缓存的范围(-128 到 127)。
因此,自动装箱过程会为c和d创建两个不同的Integer对象,它们有不同的引用地址。
System.out.println(a == b); // 输出true 127
System.out.println(c == d); // 输出false 128
System.out.println(a.equals(b)); // 输出true 127
System.out.println(c.equals(d)); // 输出true 128
String 怎么转成 Integer 的?原理?
Integer.parseInt(String s)
Integer.valueOf(String s)
字符串遍历
类型自动转换和强制转换
默认按照精度高的转换。
基础语法(关于方法)
按照try catch finally进行划分。
try(正常的逻辑代码)
- 顺序:
break ,continue ,return 的区别及作用
break 跳出整个循环,不再执行循环(结束当前的循环体)
continue 跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件)
return 程序返回,不再执行下面的代码(结束当前的方法 直接返回)
- 选择 :
switch: switch 不能作用在long 上
if:
&和&&
&&之所以称为短路运算是因为,如果&&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。很多时候我们可能都需要用&&而不是&。
- 循环
catch(这个和异常有关系)
异常:
出现分类
解决:
finally(经典面试题)
public class TryDemo {
public static void main(String[] args) {
System.out.println(test());
}
public static int test() {
try {
return 1;
} catch (Exception e) {
return 2;
} finally {
System.out.print("3");
}
}
}
31
public class TryDemo {
public static void main(String[] args) {
System.out.println(test1());
}
public static int test1() {
try {
return 2;
} finally {
return 3;
}
}
}
3
public class TryDemo {
public static void main(String[] args) {
System.out.println(test1());
}
public static int test1() {
int i = 0;
try {
i = 2;
return i;
} finally {
i = 3;
}
}
}
2
高阶使用
序列化
为什么:
类比我们生活中一些大件物品的运输,运输的时候把它拆了打包,用的时候再拆包组装。
是什么
序列化就是把 Java 对象转为二进制流,方便存储和传输。所以反序列化就是把二进制流恢复成对象。
怎么用
类实现接口Serializable 接口
泛型
为什么
虽然使用Object类型可以在一定程度上实现通用性,但泛型在类型安全性和代码重用性方面提供了更强大的支持。因此,在Java编程中,我们通常会优先使用泛型来处理需要通用性的情况。
1、泛型提供了编译时的类型检查,这大大提高了程序的安全性。使用泛型,你可以在编译阶段就指定操作的对象类型,并由编译器进行强制类型检查。相比之下,使用Object类型则会在运行时进行类型转换,这不仅效率低下,而且存在类型转换错误的风险。如果转换错误,编译器不会给出警告,只有在运行时才会报错,这增加了调试和修复错误的难度。
2、泛型提高了代码的重用性和可读性。通过泛型,你可以编写通用的代码,这些代码可以在不同类型之间重用,从而减少了重复的代码量,提高了代码的可维护性。而使用Object类型则需要手动进行类型转换,这不仅增加了代码的复杂性,而且降低了代码的可读性。
3、泛型还提供了通配符"?"等特性,这些特性进一步提高了程序的阅读性和健壮性。通配符可以用于方法的参数中,负责接收信息,使得代码更加灵活和易于理解。
是什么
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
怎么用
常用的通配符为: T,E,K,V,?
? 表示不确定的 java 类型
T (type) 表示具体的一个 java 类型
K V (key value) 分别代表 java 键值中的 Key Value
E (element) 代表 Element
注解
为什么
简化代码
是什么
Java 注解本质上是一个标记,可以理解成生活中的一个人的一些小装扮,比如戴什么什么帽子,戴什么眼镜
怎么用
where:@Target
when:@Retention
childwhere:@Inherited
文档:@Documented
反射
为什么
运行时动态获取信息
是什么
我们通常都是利用new方式来创建对象实例,这可以说就是一种“正射”,这种方式在编译时候就确定了类型信息。而如果,我们想在时候动态地获取类信息、创建类实例、调用类方法这时候就要用到反射。
怎么用
反射的原理?
我们都知道 Java 程序的执行分为编译和运行两步,编译之后会生成字节码(.class)文件,JVM 进行类加载的时候,会加载字节码文件,将类型相关的所有信息加载进方法区,反射就是去获取这些信息,然后进行各种操作。
总结
代码说白了就是属性和方法,围绕java语言本身的特点,说说在这两方面有什么用处即可。