Java必考知识点整理
线程的生命周期
线程的生命周期包含5个阶段,包括:新建、就绪、运行、阻塞、死亡。
新建:对象由Thread类或者子类声明并创建,此时对象拥有相应的内存空间和其他资源;
就绪:在对象调用线程的start()方法后,这时候线程处于等待CPU分配资源阶段;
运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态,run方法定义了线程的操作和功能;
阻塞:在运行状态的时候,可能因为某些原因导致运行状态的线程变成了阻塞状态,比如sleep()、wait()之后线程就处于了阻塞状态,这个时候需要其他机制将处于阻塞状态的线程唤醒,比如调用notify或者notifyAll()方法。唤醒的线程不会立刻执行run方法,它们要再次等待CPU分配资源进入运行状态;
死亡:如果线程正常执行完毕后或线程被提前强制性的终止或出现异常导致结束,那么线程就要被销毁,释放资源;
重载与覆盖
区别 | 覆盖 | 重载 |
---|---|---|
实现 | 子类对父类方法的重写 | 同一个类中建立多个同名方法 |
参数 | 与父类同名同参 | 与别的方法同名不同参 |
权限 | 子类不能覆盖父类的private权限 | 无 |
返回值 | 与父类方法一致 | 无 |
发生重载的条件
- 对于类的方法(包括从父类中继承的方法),方法名相同,参数列表不同的方法之间就构成了重载关系。这里有两个问题需要注意:
- 什么叫参数列表不同?是指三样东西:参数的类型,参数的个数,参数的顺序,这三者只要有一个不同就叫做参数列表不同。
- 重载关系只能发生在同一个类中吗?非也。这时候你要深刻理解继承,要知道一个子类所拥有的成员除了自己显式写出来的以外,还有父类遗传下来的。所以子类中的某个方法和父类中继承下来的方法也可以发生重载的关系。
发生覆盖的条件:
“三同一不低” 子类和父类的方法名称,参数列表,返回类型必须完全相同,而且子类方法的访问修饰符的权限不能比父类低。
子类方法不能抛出比父类方法更多的异常。即子类方法所抛出的异常必须和父类方法所抛出的异常一致,或者是其子类什么也不抛出;
被覆盖的方法不能是final类型的。因为final修饰的方法是无法覆盖的。
被覆盖的方法不能为private。否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。
被覆盖的方法不能为static。所以如果父类中的方法为静态的,而子类中的方法不是静态的,但是两个方法除了这一点外其他都满足覆盖条件,那么会发生编译错误。反之亦然。即使父类和子类中的方法都是静态的,并且满足覆盖条件,但是仍然不会发生覆盖,因为静态方法是在编译的时候把静态方法和类的引用类型进行匹配。
面向对象编程的基本特性
继承性
- 程序中的继承性是指子类拥有父类的全部特征和行为,这是类之间的一种关系。Java 只支持单继承。
封装性
- 封装是将代码及其处理的数据绑定在一起的一种编程机制,该机制保证了程序和数据都不受外部干扰且不被误用。封装的目的在于保护信息,使用它的主要优点如下。
- 保护类中的信息,它可以阻止在外部定义的代码随意访问内部代码和数据。
- 隐藏细节信息,一些不需要程序员修改和使用的信息,比如取款机中的键盘,用户只需要知道按哪个键实现什么操作就可以,至于它内部是如何运行的,用户不需要知道。
- 有助于建立各个系统之间的松耦合关系,提高系统的独立性。当一个系统的实现方式发生变化时,只要它的接口不变,就不会影响其他系统的使用。例如 U 盘,不管里面的存储方式怎么改变,只要 U 盘上的 USB 接口不变,就不会影响用户的正常操作。
- 提高软件的复用率,降低成本。每个系统都是一个相对独立的整体,可以在不同的环境中得到使用。例如,一个 U 盘可以在多台电脑上使用。
- Java 语言的基本封装单位是类。由于类的用途是封装复杂性,所以类的内部有隐藏实现复杂性的机制。Java 提供了私有和公有的访问模式,类的公有接口代表外部的用户应该知道或可以知道的每件东西,私有的方法数据只能通过该类的成员代码来访问,这就可以确保不会发生不希望的事情。
多态性
- 面向对象的多态性,即“一个接口,多个方法”。多态性体现在父类中定义的属性和方法被子类继承后,可以具有不同的属性或表现方式。多态性允许一个接口被多个同类使用,弥补了单继承的不足。
面向抽象编程
- 指当设计某种重要的类时,不让该类面向具体的类,而是面向抽象类,即设计类中的重要数据是抽象类声明的对象,而不是具体类声明的对象。
开闭原则
- 对扩展开放,对修改关闭。
线程同步
概念
是解决两个或者多个线程同时访问同一个变量,并且至少有一个线程需要修改这个变量时,如何确保不发生冲突和混乱问题的办法。
实现
给若干个线程需要同时调用的方法添加
synchronized
修饰,即对其进行加锁。注意:同时调用的方法内需要对变量具有修改操作,且此变量为共有的变量,即只有涉及到共公变量多线程修改的时候才需要加锁补充了解
Lock
接口
牢记
- 关于线程同步,需要牢牢记住的第一点是:线程同步就是线程排队。同步就是排队。线程同步的目的就是避免线程“同步”执行。这可真是个无聊的绕口令。
- 关于线程同步,需要牢牢记住的第二点是 “共享”这两个字。只有共享资源的读写访问才需要同步。如果不是共享资源,那么就根本没有同步的必要。
- 关于线程同步,需要牢牢记住的第三点是,只有“变量”才需要同步访问。如果共享的资源是固定不变的,那么就相当于“常量”,线程同时读取常量也不需要同步。至少一个线程修改共享资源,这样的情况下,线程之间就需要同步。
- 关于线程同步,需要牢牢记住的第四点是:多个线程访问共享资源的代码有可能是同一份代码,也有可能是不同的代码;无论是否执行同一份代码,只要这些线程的代码访问同一份可变的共享资源,这些线程之间就需要同步。
参考资料
接口
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
变量类型
Java语言支持的变量类型有:
- 类变量:独立于方法之外的变量,用 static 修饰。(又称静态成员变量)
- 实例变量:独立于方法之外的变量,不过没有 static 修饰。
- 局部变量:类的方法中的变量。
实例变量和类变量的区别
- 不同对象的实例变量不同
- 所有对象共享类变量
- 通过类名直接访问类变量
注:类变量似乎破坏了分装性,其实不然,当对象调用实例方法时,该方法中出现的类变量也是该对象的变量,只不过这个变量和所有的其他对象共享而已。
正则表达式
三个常用类
java.util.regex 包主要包括以下三个类:
Pattern 类: pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
Matcher 类: Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
PatternSyntaxException: PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
捕获组
捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。 例如,正则表达式 (123) 创建了单一分组,组里包含"1","2",和"3"。
捕获组是通过从左至右计算其开括号来编号 例如,正则表达式 ( A ( B ( C ) ) ),则分为( A (B( C ) ) ),( B ( C ) ),( C ) 计算心得:从左向右,依次根据左侧括号匹配右侧括号,则括号内的字符为一组。
可以通过调用 matcher 对象的 groupCount 方法来查看表达式有多少个分组。groupCount 方法返回一个 int 值,表示matcher对象当前有多个捕获组。
还有一个特殊的组(group(0)),它总是代表整个表达式。该组不包括在 groupCount 的返回值中。
正则表达式语法
在其他语言中(Perl,JS,PHP,Python,Ruby等),
\
表示:我想要在正则表达式中插入一个普通的(字面上的)反斜杠,请不要给它任何特殊的意义。在 Java 中,
\\
表示:我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。 注:在Java中需要两个\\
表示一个\
这与C++,Go类似。
参考资料
数据库
加载驱动
1 |
|
连接数据库
1 |
|
创建查询
1 |
|
处理结果集
1 |
|
释放结果集,关闭连接
1 |
|
UML类图
类图基础属性
1 |
|
类与类之间的关系
- 在UML类图中,常见的有以下几种关系:
泛化(Generalization)
实现(Realization)
关联(Association)
聚合(Aggregation)
组合(Composition)
依赖(Dependency)
泛化
继承
- 表示方法:实线+空心三角形
实现
- 表示方法:虚线+空心三角形
GUI
常用组件
顶层容器
- JFrame 框架,一般被继承
中间容器
JPanel 普通面板,最常用
JTabbedPane 选项卡面板,用于需要切换界面
控件
JLabel 标签
JButton 按钮
JTextField 文本框,一般用于做输入框
JTextArea 文本域,一般用于做显示框
JMenu 菜单
JMenuItem 菜单项
常用布局
FlowLayout
流式布局,从左向右排列,排满一行则换行
是JPanel的默认布局
GridLayout
- 网格布局,将面板按行列划分为相等的网格
CardLayout
卡片布局,将面板层叠放入容器
可以用来实现类似卡片面板的切换功能
常用方法
关于容器
setTitle() 设置标题
setSize() 设置窗口大小,(宽,高)
setVisible() 设置容器是否可见,true/false
setLayout() 设置布局,常和布局一起使用
setDefaultCloseOperation(EXIT_ON_CLOSE) 设置关闭操作
add() 添加容器,控件等
关于控件
getText() 获取文字
setText() 设置文字
append() 文本域追加文字
监听事件
ActionListener 接口
- 重写ActionPerformed(ActionEvent e)函数
KeyListener 接口
keyTyped(KeyEvent e)
keyPressed(KeyEvent e)
keyReleased(KeyEvent e)
FocusListener 接口
focusGained(FocusEvent e)
focusLost(FocusEvent e)
网络编程
服务器端
ServerSocket类
构造函数ServerSocket(port) 端口
方法 accept() 返回一个Socket对象
客户端
Socket类
构造函数Socket(ip, port) 服务器ip和端口
传输
DataInputStream(socket.getInputStream()) 通过此方法定义输入流对象
DataOutputStream(socket.getOutputStream()) 通过此方法定义输出流对象
readUTF() 从服务器/客户端接收数据
writeUTF() 向服务器/客户端发送数据
I/O流
MVC结构
MVC,即 Model 模型、View 视图,及 Controller 控制器
- View:视图,为用户提供使用界面,与用户直接进行交互。
- Model:模型,承载数据,并对用户提交请求进行计算的模块。其分为两类: 一类称为数据承载 Bean:实体类,专门用户承载业务数据的,如 Student、User 等 一类称为业务处理 Bean:指 Service 或 Dao 对象,专门用于处理用户提交请求的。
- Controller:控制器,用于将用户请求转发给相应的 Model 进行处理,并根据 Model 的计算结果向用户提供相应响应。
MVC 架构程序的工作流程
用户通过 View 页面向服务端提出请求,可以是表单请求、超链接请求、AJAX 请求等
服务端 Controller 控制器接收到请求后对请求进行解析,找到相应的 Model 对用户请求进行处理
Model 处理后,将处理结果再交给 Controller
Controller 在接到处理结果后,根据处理结果找到要作为向客户端发回的响应 View 页面。页面经渲染(数据填充)后,再发送给客户端。