Java全栈知识体系笔记
https://www.pdai.tech/md/outline/x-outline.html
面向对象的三大特性
面向对象的三大特性:封装、继承、多态
封装:利用抽象数据结构将数据和基于数据的操作封装起来,使其构成一个不可分割的整体,尽可能的隐藏内部的细节,通过对外提供接口和外界进行交互,用户不必知道内部的细节,但可以通过对外的接口来访问该对象。
继承:一个类继承另一个类,将会继承父类中所有的属性和方法,如果是私有变量的话,子类会继承到但是无法直接访问。
父类的引用指向子类的对象称为向上转型
多态:分为运行时多态和编译时多态。
编译时多态主要指方法的重载
重载,简单说,就是函数或者方法有相同的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。
namespace OOP1
{
/// <summary>
/// 编译时的多态:方法的重载
/// </summary>
public class Overload
{
/// <summary>
/// 方法的签名:包含方法的名字和参数(参数的数量和个数)
/// </summary>
/// <param name="a"></param>
public void DisplayOverload(int a)
{
Console.WriteLine("DisplayOverload: "+a);
}
/// <summary>
/// 方法的签名:包含方法的名字和参数(参数的数量和个数)
/// </summary>
/// <param name="a"></param>
public void DisplayOverload(string a)
{
Console.WriteLine("DisplayOverload: "+a);
}
/// <summary>
/// 方法的签名:包含方法的名字和参数(参数的数量和个数)
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
public void DisplayOverload(string a, int b)
{
Console.WriteLine("DisplayOverload: "+a +b);
}
}
}
运行时多态:是指对象的引用所指向的具体类型只有在运行时才能确定。
运行时多态有三个条件:
- 继承
- 重写
- 向上转型
Java基础知识点
数据类型
数据类型:八大基本数据类型,每个基本数据类型都有对应的包装类
boolean、byte、short、int、long、float、double、char
缓存池:int的缓存池大小是 -127~128
在这个范围内,使用
Integer a = 2; Integer b = 2;
a == b (true)
Integer c = new Integer(3);
Integer d = new Integer(3);
c == d (false)
使用Integer a = 2; 会从缓存池中找到这个值
String、StringBuffer、StringBuilder
String 不可变,每次new String(“123”)会重新创建一个对象,用字符串直接赋值会从字符串常量池中找是否有相同的对象赋值给它
StringBuffer可变,是线程安全的,内部使用 synchronized 进行同步
StringBuilder可变,不是线程安全的
String.intern() 可以把某个String对象放到字符串常量池中,并返回他的引用
运算
参数传递
Java中参数的传递是值传递,而不是引用传递。
一个对象的引用作为方法的参数传递时,传递的是对象引用的一个拷贝,因此如果在方法内部改变这个对象引用指向的对象的字段值可以改变原对象,但是如果改变对象引用指向的对象,对原来的对象引用没有影响
java中隐式类型转换不能向下转型,必须显式的声明
switch中不能选择long类型
继承
抽象类不可被实例化,他的方法可以是没有实现的抽象的方法,也可以有实现的方法。
在java8之前,接口可以看做是完全抽象的类,没有任何的方法的实现。但是在java8以后接口中也可以定义实现的方法和字段。方法是public、字段是public static final
super可以调用父类的构造方法完成父类的初始化操作
重写:基于子类继承了父类,而子类中重写了从父类中继承过来的某个方法
方法名、参数类型、参数顺序完全相同,修饰符的范围子类可以扩大但不能缩小
- 重载:一个类中方法名相同但是参数类型、参数个数、参数顺序有一个不同,不能只以返回值类型不同来重载。
Object通用方法
包装类型中,equals 比较对象的值是否相同,== 比较对象地址是否相同
hashCode()方法可以返回某个对象的哈希值,这个哈希值用来区别不同的对象
toString()、clone()
关键字
final可以修饰变量、方法
修饰变量的话,这个变量只能被赋值一次后就不能更改了
修饰方法的话,这个方法无法被子类覆盖(重写)
static修饰变量,这个变量属于这个类,这个类实例化后的所有对象都共享这一个static变量
static修饰方法,这个方法属于这个类,static类中只能使用静态变量和方法、不能使用非静态的
反射
Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能调用他的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法成为Java语言的反射机制。
反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。
一般我们的对象的类型在编译期间就已经确定了,我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。
Java反射提供的功能:
- 在运行时判断一个对象属于哪个类
- 在运行时构造任意一个类的对象
- 在运行时判断某个类中的所有属性和方法(甚至是private方法)
- 在运行时调用任意一个对象的方法
反射的基本应用:
- 获取Class对象
- 判断是否为某个类的实例
- 创建实例
- 获取某个Class对象的方法
- 获取构造器信息
- 获取类的成员变量
- invoke调用方法
- 利用反射创建数组
Java 与 C++ 的区别
- Java 是纯粹的面向对象语言,所有的对象都继承自 java.lang.Object,C++ 为了兼容 C 即支持面向对象也支持面向过程。
- Java 通过虚拟机从而实现跨平台特性,但是 C++ 依赖于特定的平台。
- Java 没有指针,它的引用可以理解为安全指针,而 C++ 具有和 C 一样的指针。
- Java 支持自动垃圾回收,而 C++ 需要手动回收。
- Java 不支持多重继承,只能通过实现多个接口来达到相同目的,而 C++ 支持多重继承。
- Java 不支持操作符重载,虽然可以对两个 String 对象支持加法运算,但是这是语言内置支持的操作,不属于操作符重载,而 C++ 可以。
- Java 的 goto 是保留字,但是不可用,C++ 可以使用 goto。
- Java 不支持条件编译,C++ 通过 #ifdef #ifndef 等预处理命令从而实现条件编译。
补充:
try..with…rource 可以自动的关闭一些在try中创建的变量
泛型
泛型的本质是为了参数化类型,在不创建新类型的情况下,通过泛型指定不同类型来控制形参具体限制的类型。在泛型的使用过程中,操作的数据类型指定为一个参数,这种参数类型可以使用在接口、方法、类上,称为泛型接口、泛型方法、泛型类。
引入泛型的意义:适用于多种数据类型执行相同的代码。(代码复用)
泛型类、泛型接口、泛型方法
使用<? extends E> 指定泛型的上限,使用<? super E> 指定泛型的下限
如何理解java中的泛型是伪泛型
泛型是jdk1.5加入的,java语法上支持泛型,但是在编译时会擦除所有的泛型,“类型擦除”会替换所有的泛型为具体的类型。
注解
注解用于对代码进行说明,可以对类、方法、字段、方法参数、局部变量等进行注解。他的作用:生成文档、编译检查、编译时动态处理、运行时动态处理。
注解的分类:
Java中自带的标准注解:@Override、@Deprecated、@SuppressWarnings;元注解:
元注解:用于定义注解的注解。包括@Document、@Target、@Retention、@Inherited。Java8中新增 @Repeatable、@Native
自定义注解
元注解详细解释:
@Target 标明注解使用的范围,参数如下
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
@Retetion用于标明注解被保留的阶段,参数如下
public enum RetentionPolicy {
SOURCE, // 源文件保留
CLASS, // 编译期保留,默认值
RUNTIME // 运行期保留,可通过反射去获取注解信息
}
注解不支持继承,但是如果某个类使用了被@Inherited修饰的注解,会让这个类的子类自动拥有这个注解
异常
异常是指程序运行中出现的各种状况,Java中通过Throwable的各种子类描述不同的异常。Throwable是Java中所有错误和异常的超类,他有两个子类 Error、Exception,用来指示发生了异常情况。
Error类及其子类:程序中无法处理的错误,表示应用程序出现了严重的错误。
Exception类及其子类:分为运行时异常和编译时异常。
编译时异常必须在编写代码中解决,要么用try catch捕获要么用throw抛出
运行时异常通常是由逻辑错误,算术问题引出,编译器无法识别,只能在编写中尽量避免逻辑错误。
异常可以自定义,自定义时需要继承Exception类。
异常分为可查的异常和不可查的异常。可查的异常包括编译时异常,不可查的异常包括运行时异常和Error错误,对于可查的异常必须进行处理try catch或者throw抛出
throws用来声明一个异常,告知方法调用者可能出现的异常。throw用来抛出一个异常(自己解决不了,抛出给上层)
Java类加载机制
Java类加载主要有:加载、验证、准备、解析、初始化五个过程,加载、验证、准备、初始化是按顺序开始的,解析则不一定
类的加载:查找并加载类的二进制数据。
反射
Java集合框架
Collection容器主要包括Collection和Map两种,Collection存储着对象的集合,而Map存储着键值对。
Set
TreeSet、HashSet、LinkedHashSet
List
ArrayList、Vector、LinkedList
Queue
LinkedList
PriorityQueue
Map
TreeMap、HashMap、HashTable、LinkedHashMap
线程
多线程的出现是要解决什么问题的?
CPU、内存、I/O设备的速度是有极大的差异的,为了合理利用CPU的性能,平衡这三者的速度差异。
线程不安全是指什么? 举例说明
如果多个线程对同一个共享数据进行访问而不采取同步操作的话,那么操作的结果是不一致的。
并发出现线程不安全的本质什么?
可见性,原子性和有序性。
可见性:CPU缓存引起
int i = 0;
i = 10;
j = i;
原子性:(分时复用引起)
一个操作或多个操作,要么不执行,要么全部执行,并且过程中不能被任何因素打断。
转账问题
有序性:重排序引起
即程序执行的顺序按照代码的先后顺序执行。
Java是怎么解决并发问题的? 3个关键字,JMM和8个Happens-Before
三个关键字:volatile、synchronized、final
Happens-Before规则
原子性:Java内存模型只保证了基本读取和赋值是原子性操作
可见性:volatile关键字可以保证可见性,变量被volatile修饰时,有其他线程需要读取时,他会保证修改的值立即被更新到主存,他会去从内存中读取新值。
而普通的共享变量不能保证可见性,因为普通变量被修改后,什么时候被写入主存是不确定的,当其他线程读取时,很有可能读取到的是旧值。
synchronized可以保证同一时刻只有一个线程获取锁,然后执行同步代码,并且在释放锁之前会将更新的值写入主存,从而保证其可见性。
有序性:volatile、synchronize
线程安全是不是非真即假? 不是
线程安全有哪些实现思路?
如何理解并发和并行的区别?
Synchronized
- Synchronized可以作用在哪里? 分别通过对象锁和类锁进行举例。
方法、对象。
对象锁:包括方法锁和同步代码块锁。
Synchronized本质上是通过什么保证线程安全的? 分三个方面回答:加锁和释放锁的原理,可重入原理,保证可见性原理。
Synchronized由什么样的缺陷? Java Lock是怎么弥补这些缺陷的。
Synchronized和Lock的对比,和选择?
Synchronized在使用时有何注意事项?
Synchronized修饰的方法在抛出异常时,会释放锁吗?
多个线程等待同一个snchronized锁的时候,JVM如何选择下一个获取锁的线程?
Synchronized使得同时只有一个线程可以执行,性能比较差,有什么提升的方法?
我想更加灵活地控制锁的释放和获取(现在释放锁和获取锁的时机都被规定死了),怎么办?
什么是锁的升级和降级? 什么是JVM里的偏斜锁、轻量级锁、重量级锁?
不同的JDK中对Synchronized有何优化?
Java内存模型
线程之间的通信机制有两种:共享内存和消息传递。
线程
- 线程有哪几种状态? 分别说明从一种状态到另一种状态转变有哪些方式?
初始、就绪、执行、等待、终止
通常线程有哪几种使用方式?
基础线程机制有哪些?
线程的中断方式有哪些?
线程的互斥同步方式有哪些? 如何比较和选择?
线程之间有哪些协作方式?
参考文章:
著作权归https://pdai.tech所有。 链接:https://www.pdai.tech/md/java/basic/java-basic-lan-basic.html
复习专栏
Day2复习(纯手敲)
面向对象三大特性:封装、继承、多态
封装:用抽象的数据类型把数据和操作数据的方法封装在一起,形成一个整体,通过对外的接口与外部联系,这样用户不必知道内部的细节,但可以通过对象对外提供的接口来访问该对象。
优点:减少耦合,可以独立的开发测试;减轻维护的负担,更容易被程序员理解;
提高代码的重用性。
继承:一个类可以继承另一个类从而获得他的属性和方法。java只支持单继承,但可以实现多个接口
多态:分为运行时多态和编译时多态
编译时多态指的是方法的重载,方法名相同,参数的类型、个数、顺序不同
运行时多态指的是:程序中定义的对象引用所指向的具体类型在运行时才确定。
父类的引用可以指向子类的对象,叫做向上转型。
运行时多态的条件:继承、向上转型、覆盖
Java基础知识
java有八种基本类型,boolean、byte、short、int、long、double、float、char
每种都有其对应的包装类,包装类可以自动装箱拆箱。如 Integer i = 1;
Integer的缓存池大小为 -128~127 ,在这个范围内,Integer包装类在赋值的时候会检查缓存池有没有相同的值。
String、StringBuffer、StringBuilder
String长度不可变,使用new String()必定会创建一个新对象在堆里面,而如果使用字符串赋值的方式,字符串会检查字符串常量池,如果没有会放入,如果有会返回常量池中的地址。
StringBuffer可变、StringBuilder可变。两者的区别是StringBuffer是线程安全的,其中加了锁,StringBuilder不是线程安全的
String.intern()函数可以将字符串值放入常量池并返回这个字符串的一个引用
运算
Java不支持向下的隐式转换,比如double型的数据不能直接赋值给float。
当采用运算符计算时,java会自动将类型提升进行运算,比如:
byte a = 1, b = 2;
byte c = a + b; 会报错,因为两个byte被提升为int型
byte、short会被提升为int,float和double运算会被提升为double
?继承的访问权限:如果修饰为private则子类无法访问,protected则子类可以访问,
public所有类都可以访问
抽象类是具有抽象方法的类,不可实例化,接口是全部为抽象方法的类,是抽象类的特例。jdk1.8开始接口中可以定义一些默认的已经实现的方法
super用来调用父类的构造函数帮助对子类进行初始化操作。
重写和重载:
重写指的是在继承中,子类重写了父类中已经有的一个方法,方法名、参数完全和父类中的方法相同。
重载指的是在同一个类中,一些方法名相同,但是参数个数、参数类型、参数顺便不尽相同的方法,他们是对这个方法的重载。
Object的方法
Object中hashCode返回一个哈希值
equals比较的是两个对象是否相同,== 比较的是对象引用的地址是否相同。
final修饰过的属性只能被赋值一次后,就不能再改变了。修饰过的方法不可被重写(覆盖)
static修饰变量,这个变量属于这个类,在类加载时初始化,被这个类实例化出来的所有对象共享。static修饰方法,称为静态方法,静态方法中不能使用类中定义的非静态的方法和变量
反射:反射指的是Java在运行时可以获取自身类的信息
泛型:泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数可以用在类、接口、方法中,分别被称为泛型类、泛型接口、泛型方法。
引入泛型的意义:适用于多种数据类型执行相同的代码;泛型的类型在使用时指定,不需要强制转换(它是类型安全的,编译器会检查类型)
Java泛型这个特性是从JDK1.5加入的, Java在语法上支持泛型,但是在编译阶段会进行“类型擦除”,所有的泛型表示都会被替换为具体的类型,就像完全没有泛型一样。
Day3复习
Java面向对象的三大特性:封装、继承、多态
封装:用抽象数据类型将数据和基于数据的操作封装在一起,尽可能的隐藏内部的信息,通过对外的接口和外界联系,用户无需知道内部的细节,只需要通过对外的接口和这个对象发生联系。
继承:一个类可以继承另一个类获取他所有的属性和方法。父类引用指向子类的对象叫做向上转型
多态:包括运行时多态和编译时多态。编译时多态主要指重载。方法的重载指的是方法名相同,但是参数类型、参数个数、参数顺序有一个不同。
运行时多态指的是父类的引用指向的对象在运行时才能确定。运行时多态发生的条件有:继承、重写、向上转型。
final可以修饰变量、方法、类
修饰变量,这个变量如果是基本数据类型,则这个变量的值只能赋值一次,之后不能改变,如果是引用,那么不能修改这个引用指向其他的对象,但是指向的对象本身可以修改。
修饰方法,这个方法不能被覆盖。
修饰类,这个类不能被继承。
反射:反射可以在运行时获取任何类的属性和方法,这个类可以在运行时才加载进来,可以使用Class.forName(“”)的形式控制类的加载。
反射的应用:1.可以判断某个对象是否是某个类2.可以获取某个类的属性和方法
注解:注解主要用来做一些配置和标记的作用
泛型:泛型是jdk1.5引入的,Java语法上支持泛型,但是在编译时会进行类型擦除,将<>中的泛型替换成具体的类型,和没有泛型一样。
Java和C++的区别:
- Java是面向对象的语言,所有类都继承Object类。C++为了兼容c,即是面向对象,也支持面向过程。
- Java程序编译后生成的字节码在JVM虚拟机上运行,因此具有跨平台的性质,而C++不能跨平台
- Java具有垃圾回收机制,可以自动回收不再使用的内存。而C++需要手动释放空间。
- Java不支持多继承,只能采用实现多个接口来实现这个功能,c++支持多继承
- Java中goto是保留字但不能使用,C++可以试用goto
- Java不支持条件编译,C++支持条件编译
- Java不支持操作符的重载,c++可以
- Java 没有指针,它的引用可以理解为安全指针,而 C++ 具有和 C 一样的指针。