文章目录
代码块
定义
由若干条Java语句组成,并且用一对大括号{}
括起来的结构,叫做代码块
分类
根据定义的位置不同,声明方式不同分类
-
局部代码块
语法:{}
位置:定义在局部位置 -
构造代码块
语法:{}
位置:成员位置
说明:构造代码块内部定义的变量 —> 局部变量 —> 只在构造代码块内部生效 -
静态代码块
语法:static{}
位置:成员位置
说明:静态代码块内部定义的变量 —> 局部变量 —> 静态代码块内部生效 -
同步代码块
synchronized(){
// 同步代码块
}
构造代码块
作用
给成员变量赋值用的
给成员变量赋值的方式:
- 默认赋值
- 显示赋值
- 构造方法赋值
- 构造代码块
研究赋值的顺序:
- 默认赋值永远是第一步
- 构造代码块如果写在上面,则构造代码块先执行
构造代码块如果写在下面,则显示赋值先执行
结论:构造代码块跟显式赋值谁先执行 >>>>> 写在上面的先执行 - 构造方法赋值永远是最后一步
注意事项
- 经过反编译操作(通过IDEA),构造代码块中的内容被加入到了每个构造方法中前面
- 整个过程中,构造代码块和显示赋值的代码只会执行一次,不会执行多次
静态代码块
作用
可以被认为在类加载过程中自动调用的一个静态的方法,可以给静态成员赋值
给静态成员赋值的手段
- 默认赋值
- 显示赋值
- 静态代码块,特点是在类加载过程中一定会执行
赋值顺序
- 默认赋值
- 看一下静态代码块和显式赋值谁在上面(书写顺序)
结论:谁在上面谁先执行,先执行的内容会被后执行的内容覆盖掉 - 构造方法
用途
- 复杂的静态成员变量的赋值
- 如果一段代码,在类的全局,从始至终,只运行一次,就可以写到静态代码块中。(类似于类加载只加载一次)
注意事项
- 静态代码块在类加载过程中被当做自动执行的静态方法,不能访问非静态
- 当需要使用复杂的代码给静态成员变量赋值的时候,可以使用静态代码块
- 静态代码块也经常被用来测试类加载的顺序。(重要)
对象的结构
类加载的过程
- 加载
通过类加载器(ClassLoader)加载类,读取字节码文件,.class
文件,读取到内存中(二进制文件),在这个过程中,在内存中会生成这个类所对应的字节码文件对象(java.lang.Class),这个字节码文件对象包含了类中的所有信息(All) - 链接
(1)验证:主要进行字节码文件的正确性的校验
(2)准备:为类中的静态成员分配内存,赋予默认初始值
(3)解析:把符号引用(用一组符号来描述被引用的目标)替换为直接引用(真实的内存地址) - 初始化
执行静态代码块中的内容,给静态成员显示赋值
导包
package关键字
作用
写在java文件的第一行
表明java文件中的类是属于哪个包
注意事项
- 包名在书写时,如果存在多级包名,需要使用用
.
隔开 - package声明必须处在一个Java文件有效代码的第一行,否则会报错
- 注释不算有效代码,将package声明放在注释下面也是可以的
- 建议将package声明永远放在Java源文件真正意义上的第一行
- 多数情况下,我们使用idea新建Java文件是无需关系package声明的,因为idea会自动生成
- 但是当你从网上或者其它途径弄到的一些代码,可能会出现包名错乱的情况
- 这时建议直接删除package声明,然后"Alt + 回车"类名报错的地方即可
全限定类名
import关键字
语法
import 全限定类名;
注意事项
-
import导包语句应该放在package声明之后,有效代码之前。
正常情况下,我们使用某个类时,IDEA会自动导包,不用太关心这条语句的位置。
一般只需要注意不要用IDEA导错包就可以了。
-
像String、System、Math等常用类很明显不是同包下的类,但我们并没有进行导包操作。
- 这是因为在Java当中的,“java.lang包”是Java的核心类包,具有隐式的导包。
- 注意"java.lang包"下的所有类,是隐式的导入了每个Java类,而不是没有导入!
-
实际上完全可以不导包去使用不同包下类,这时要明确指出这个类的所属包,也就是要使用全限定类名。
但是一般情况下,全限定类名都很长,导包仍然是更好的手段。
-
但是导包总不是都好用,在极少的情况下:
比如,在Demo类中,想要同时访问两个包onepackage、anotherpackage下的两个Student类。
咋办?
很简单,其中一个Student类使用全限定类名,另一个导包或者就近原则直接使用就可以了。
(当然条件允许的情况下,干脆把其中一个Student改名会更好。)
智能导入
语法
import + 包名.*;
eg:
import java.util.*;
静态导入
import
还可以和static
一起使用,称之为静态导入
普通import导入导入的是某个类,而静态导入导入的是静态成员(变量和方法)
以往我们访问不同包下的类的静态成员,是通过类名.静态成员名的形式访问的
而如果使用静态导入的语法将这些不同包的类当中的静态成员导入,就可以省略相应的类名~
语法
import static 全限定类名.*;
import static 全限定类名.静态成员;
包的作用
-
在工程中用于组织Java文件,分类。
-
类名的空间管理,同包禁止同名类,避免类名冲突。
注:前两点和操作系统中的文件夹作用是一致的。
-
提供包一级的封装及访问权限控制。(面向对象后面的知识)
包的命名
-
全部小写英文单词,实际开发中多以反转公司域名为开头。
eg:com.baidu.package1 -
如果是名词,使用单数形式,不要用复数形式。
编译单元
- 一个Java源代码文件(Java文件)称为一个编译单元。
- 一个Java源代码文件由三部分组成:
- 所属包的声明,即package声明。
- 导入声明。即import声明。
- 主体声明。
- 一个编译单元只能有一个public class,该类的类名必须与文件名相同。但可以允许有多个非public class。经过编译后,该编译单元下的所有class都会生成对应的、独立的字节码文件。
访问权限控制符
在Java语言中,一切事物(类和类的所有成员)都具有(或显示定义或隐式定义的)访问权限,而这种语言层面的访问权限控制,是由访问权限修饰符实现的。
4个访问级别
-
private
只能是同类中进行访问 -
默认权限(缺省)
只能是同包中进行访问 -
protected
-
public
同包或者不同包都可以访问(相当于没有访问权限)
注意事项
- 代码块没有访问权限
- 局部变量没有访问权限
class访问级别
只有两个访问级别:
- public
- 默认
作用
-
专门提供给外界使用的,推荐使用的,用
public
。告诉别人:这里是你需要关注、了解和使用的地方。所有明确提供给外界使用,实现功能的方法,需要用public修饰。
-
不应该触碰的地方,用私有
private
修饰,告诉别人:这里你不需要你看,也不需要你管。具体的案例是:
-
工具类,既然所有的方法,都可以直接用“类名.”去调用,不需要创建对象!
既然不需要对象,那就干脆不要创建对象,直接把这个功能去掉!
所有工具类,都应该私有化无参构造方法!!
-
类中需要提供给外界使用的方法的实现过程中,经常需要一些“中间的过程”方法。
这些方法不需要提供给外界使用,仅作为内部实现功能使用。
所有类中的"中间方法"都应该私有化它们!
-
工厂设计模式。
指的是不通过自身构造器创建对象,而是通过“工厂”去创建对象,这时类的构造器应该私有。
-
工厂设计模式
定义
一种创建对象的方式,只需要告诉我生产什么对象,生产对象的过程交给工厂去做,不需要关心内部的实现细节。
举例
public class StudentFactory{
private StudentFactory(){
}
// 提供一个静态的方法,给外部访问
public static Student getInstance(String className, String name, int age)
throws Exception
{
// 要使用反射
Class<?> c = Class.forName(className);
Constructor<?> constructor = c.getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true);
// 创建构造方法
Student student = constructor.newInstance(name, age);
// 最终 ---> 返回一个学生对象
return student;
}
}
好处
-
尽量私有化,方便自己修改代码,隐藏实现细节。
-
如果不能私有化,那也应该尽量少的给予访问权限,先从默认权限开始考虑。
-
只有确定这个结构,一定需要在外部(尤其是不同包下)被访问时,才考虑给public,尽量少给public
权限这个东西,要吝啬,不要"大方"!
单例设计模式
定义
单例设计模式是一种应用程序维护实例的方式,
单例即1个,应用程序中只有1个唯一的实例对象(全局共享的)。
应用场景
- 回收站
- 统计用户访问量,计数器(单例)
实现步骤
- 构造方法私有
- 提供一个自身的全局的静态成员变量
- 提供一个
public
的静态方法
两种模式
- 懒汉模式(懒加载)
- 懒汉指的是用到的时候才去创建对象
- 饿汉模式(立即加载)
- 饿汉指的是不管用不用, 先去把对象创建好
懒汉模式(懒加载)实现单例(线程不安全)
public class Singleton{
// 提供一个全局的自身成员变量
private static Singleton instance;
// 构造方法私有
private Singleton(){
}
// 提供一个静态的public的访问,给外部访问,从而获得唯一的实例对象
public static Singleton getInstance(){
// 做判断
if( null == instance){
instance = new Singleton();
}
// 最终要返回这个唯一的对象
return instance;
}
}
饿汉模式(立即加载)实现单例(线程安全)
public class Singleton{
// 提供一个全局的自身成员变量
private static Singleton instance = new Singleton();
// 构造方法私有
private Singleton(){
}
// 提供一个静态的public的访问,给外部访问,从而获得唯一的实例对象
public static Singleton getInstance(){
// 最终要返回这个唯一的对象
return instance;
}
}