static关键字
使用static关键字来修饰成员变量和成员方法,被修饰的成员属于类,而不在属于用类
new
出的实例对象。也可使用对象来调用,是因为编译器会在编译的时候替换成类,建议直接使用类来调用。
静态变量
使用
static
修饰成员变量就是类变量,该类实例化的对象都共享变量值。该类型变量都在内存中方法区的静态区,供每个对象共享,类变量是随着类加载而加载,只加载一次。
Cat.java
public class Cat {
String name;
int age;
static String type;
void say(String name) {
System.out.println(this.name + "说"+name+"你好。");
}
}
Test.java
public class Test {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "mm";
cat.age = 10;
cat.type = "白猫";//不建议使用对象.静态变量,此处为了演示
Cat cat1 = new Cat();
cat1.name = "xm";
cat1.age = 11;
cat1.type = "黑猫";//不建议使用对象.静态变量,此处为了演示
//正确的调用方式 类名.静态变量
System.out.println(Cat.type);//黑猫
}
}
静态方法
使用
static
修饰成员方法就是是类方法,不是类方法,必须先实例化对象才能使用方法,而类方法也就是静态方法,可以直接通过类名.方法名()
调用,例如许多工具类Arrays等。本类的静态方法可以省略类名调用。
将上述Cat中的say(String name)
方法用static修饰,直接用类名调用。(也可使用对象来调用,不建议使用)
Cat.say("mm");
- 成员方法可以访问静态变量
- 静态变量不能访问非静态变量
- 内存中加载先有静态内容,后有非静态内容
- 静态方法不能用
this
关键字,因为this
谁调用,就代表那个对象。
静态代码块
在类的成员变量处使用
static{}
来定义静态代码块,优先于非静态代码(优先于main方法和构造方法)。随类的加载而执行一次,常用于给静态变量初始化赋值。
Cat.java
public class Cat {
static String name;
static int age;
static String type;
static{
name = "咪咪";
age = 10;
type = "猫";
}
public Cat(){
System.out.println("构造方法执行了");
}
}
Test.java
public class Test {
public static void main(String[] args) {
Cat cat = new Cat();
//执行结果:
//静态代码块执行了
//构造方法执行了
}
}
final关键字
final代表最终的,不可变的
- 修饰类
public final class 类名{}
其中不能够继承这个类,与abstract不能同时使用,不能够重写任何成员方法。
- 修饰成员方法
public final 返回值类型 方法名(){}
不能够重写父类中的final方法,与abstract不能同时使用。
- 修饰局部变量
public final 返回值类型 方法名(){
final 数据类型 变量名 = 值;
}
只能赋值一次,再不会改变。
- 修饰成员变量
public final class 类名{
final 数据类型 变量名 = 值;
}
成员变量具有默认值,使用final
修饰必须手动赋值。
访问权限修饰符
java
中的访问控制符,修饰类、属性、方法的访问权限。
public
修饰,任何地方都可访问。protected
修饰,在类内部、同一个包中、子类中可以访问,不可修饰外部类。子类与父类不在同一包中,子类实例可以访问其从父类继承而来的 protected 方法,而不能访问父类类实例的protected方法。default
修饰(即默认什么也不写),在类内部和同一个包中都可以访问(不建议使用)。private
修饰,仅当前类内部可以访问,不可修饰外部类。private
修饰的方法不可被继承。
权限修饰符 | 同一个类 | 同一个包 | 不同包的子类 | 不同包的非子类 |
---|---|---|---|---|
Private | √ | |||
Default | √ | √ | ||
Protected | √ | √ | √ | |
Public | √ | √ | √ | √ |
包
包的作用是为了区别重名的类,更好的组织类
java
中默认的基础包是java.lang.*
编译器可以自动导入,真正的类名为包名.类名
。- 包与目录一样采用多层结构,不同包中相同的类,应该加上包名区别。
- 使用包还可以通过定义权限来访问包中的类。
java.lang
与java.lang.reflect
没有直接关系,第二个仍然需要导入。
定义
package 包名.下级包名.[.....];
导包
import 包名.下级包名.*[或类名];
使用固定包中的类就需要进行导包操作,使用import static
可以导入一个类的静态字段和静态方法。
jar包
为了方便管理字节码文件,将字节码文件打成一个压缩包(jar包)与zip压缩包一样来进行管理,可以将包下的目录和目录下的文件都打包。
其中在根目录下创建/META-INF/MANIFEST.MF
文件,MANIFEST.MF
是jar包描述信息可以配置启动类
Manifest-Version: 1.0
Created-By: 14.0.2(JDK版本) (Oracle Corporation)
Class-Path: .(依赖的类库)
Main-Class: 完整的类名(包名.类名)//下一行空行必须留
其中编译到指定文件夹的命令为:
javac [可选-cp指定依赖的包] 编译文件名或*.java -d 目标位置
制作jar的命令为:
-
-c 创建新的归档文件
-
-t 列出归档目录
-
-x 解压缩已归档的指定(或所有)文件
-
-u 更新现有的归档文件
-
-v 在标准输出中生成详细输出
-
-f 指定归档文件名
-
-m 包含指定清单文件中的清单信息
-
-e 为捆绑到可执行 jar 文件的独立应用程序,指定应用程序入口点
-
-0 仅存储;不使用任何 ZIP 压缩
-
-M 不创建条目的清单文件
-
-i 为指定的 jar 文件生成索引信息
-
-C 更改为指定的目录并包含其中的文件
jar -cvfm jar包命名 MENIFEST.MF文件路径 打包文件[ 打包文件1等文件列表或*]
或自己创建/META-INF/MANIFEST.MF
文件
jar --create --file 包名.jar --main-class Main -C .\ .[打包目录 jar包存放路径]
使用命令:
java -jar jar包名
模块
JDK9
之后引入,为了解决jar包之间的依赖,模块之间的依赖关系写入module-info.java
文件。所有的模块都直接或间接地依赖java.base
模块,java.base
模块不依赖任何模块。
定义
module-info.java
文件中使用module
关键字定义,其中module-info.java
文件在模块根目录下。
module 模块名 {
requires java.base; // 默认导入的模块
}
编译
可以通过如下命令编译
javac -d 路径/模块名 编译文件名
或将文件编译打成jar包
封装模块
jmod create --class-path 路径\模块名 模块名.jmod
或jar包封装成模块
jmod create --class-path 包名.jar 模块名.jmod
执行
可以通过以下命令执行
java --module-path 模块所在路径[或包名.jar] -m[或--module] 模块名/主类名[或模块名(指定加载主类适用)]
打包JRE
jdk9
之后把jdk
核心类库rt.jar
拆分为.jmod
模块,可以把实际运行java
程序所需要的模块打包成jre
来减少体积。
jlink --module-path 模块名.jmod --add-modules java.base,[所需模块列表],程序模块名 --output 打包jre存放路径
访问时:
打包jre存放路径/bin/java -m[或--module] 模块名/主类名[或模块名(指定加载主类适用)]
权限
如果模块中的某些类需要让外界访问需要在
module-info.java
中申明要导出的包供外部模块访问。
module 模块名{
export 包名;
requires java.base;
}
留言