Java基础系列文章
Java基础(十):关键字static、代码块、关键字final
Java基础(十八):java比较器、系统相关类、数学相关类
目录
一、关键字static
- 如果想让一个成员变量被类的
所有实例所共享
,就用static修饰即可,称为类变量(或类属性)!!! - 在类中声明的实例方法
- 在类的外面必须要先创建对象,才能调用
- 但是有些方法的调用者和当前类的对象无关,这样的方法通常被声明为
类方法
- 由于不需要创建对象就可以调用类方法,从而简化了方法的调用
static关键字
- 使用范围:可用static修饰属性、方法、代码块、内部类
- 被修饰后的成员具备以下特点:
- 随着类的加载而加载
- 优先于对象存在
- 修饰的成员,被所有对象所共享
- 访问权限允许时,可不创建对象,直接被类调用
1、静态变量
静态变量的特点
- 静态变量值是所有对象共享
- 静态变量在本类中,可以在任意方法、代码块、构造器中直接使用
- 如果权限修饰符允许,在其他类中可以通过“
类名.静态变量
”直接访问,也可以通过“对象.静态变量
”的方式访问
(但是更推荐使用类名.静态变量的方式) - 静态变量的get/set方法也静态的,当局部变量与静态变量
重名时
,使用“类名.静态变量
”进行区分
对比静态变量与实例变量
- 个数
- 静态变量:在内存空间中只有一份,被类的多个对象所共享
- 实例变量:类的每一个实例(或对象)都保存着一份实例变量
- 内存位置
- 静态变量:jdk6及之前:存放在方法区。 jdk7及之后:存放在堆空间
- 实例变量:存放在堆空间的对象实体中
- 加载时机
- 静态变量:随着类的加载而加载,由于类只会加载一次,所以静态变量也只有一份
- 实例变量:随着对象的创建而加载。每个对象拥有一份实例变量
- 调用者
- 静态变量:可以被类直接调用,也可以使用对象调用
- 实例变量:只能使用对象进行调用
- 消亡时机
- 静态变量:随着类的卸载而消亡
- 实例变量:随着对象的消亡而消亡
举例
2、静态方法
静态方法的特点
- 在static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构
- 静态方法可以被子类继承,但不能被子类重写
- 因为不需要实例就可以访问static方法,因此static方法内部不能有this,也不能有super。如果有重名问题,使用“类名.”进行区别
二、理解main方法的语法
- 由于JVM需要调用类的main()方法,所以该方法的访问权限必须是
public
- 又因为JVM在执行main()方法时不必创建对象,所以该方法必须是
static
的 - 该方法接收一个String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数
- 又因为main() 方法是静态的,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员
举例:
三、代码块
1、静态代码块
- 随着类的加载而执行
- 由于类的加载只会执行一次,进而静态代码块的执行,也只会执行一次
- 作用:用来初始化类的信息
- 内部可以声明变量、调用属性或方法、编写输出语句等操作
- 静态代码块的执行要先于非静态代码块的执行
- 如果声明有多个静态代码块,则按照声明的先后顺序执行
- 静态代码块内部只能调用静态的结构(即静态的属性、方法),不能调用非静态的结构(即非静态的属性、方法)
2、非静态代码块
- 随着对象的创建而执行
- 每创建当前类的一个实例,就会执行一次非静态代码块
- 作用:用来初始化对象的信息
- 内部可以声明变量、调用属性或方法、编写输出语句等操作
- 静态代码块的执行要先于非静态代码块的执行
- 如果声明有多个非静态代码块,则按照声明的先后顺序执行
- 非静态代码块内部可以调用静态的结构(即静态的属性、方法),也可以调用非静态的结构(即非静态的属性、方法)
3、实例变量赋值顺序
- 先加载父类,通过构造器第一行,隐藏的super()方法找父类
- 代码块在构造器之前执行
- 显示赋值和代码块中赋值顺序,由先后顺序决定
举例1
class Root{
static{
System.out.println("Root的静态初始化块");
}
{
System.out.println("Root的普通初始化块");
}
public Root(){
System.out.println("Root的无参数的构造器");
}
}
class Mid extends Root{
static{
System.out.println("Mid的静态初始化块");
}
{
System.out.println("Mid的普通初始化块");
}
public Mid(){
System.out.println("Mid的无参数的构造器");
}
public Mid(String msg){
//通过this调用同一类中重载的构造器
this();
System.out.println("Mid的带参数构造器,其参数值:"+ msg);
}
}
class Leaf extends Mid{
static{
System.out.println("Leaf的静态初始化块");
}
{
System.out.println("Leaf的普通初始化块");
}
public Leaf(){
//通过super调用父类中有一个字符串参数的构造器
super("尚硅谷");
System.out.println("Leaf的构造器");
}
}
public class LeafTest{
public static void main(String[] args){
new Leaf();
//new Leaf();
}
}
结果:
Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:尚硅谷
Leaf的普通初始化块
Leaf的构造器
- 先加载父类静态,再到子类静态
- 先顺序执行父类普通代码块、构造器,再执行子类普通代码块、构造器
举例2
- 第一个静态代码中的x作用域只在当前代码块中,与静态成员变量x是两个变量
public class Test02 {
static int x, y, z;
static {
int x = 5;
x--;
}
static {
x--;
}
public static void method() {
y = z++ + ++z;
}
public static void main(String[] args) {
System.out.println("x=" + x);
z--;
method();
System.out.println("result:" + (z + y + ++z));
}
}
举例3
public class Test03 {
public static void main(String[] args) {
Sub s = new Sub();
}
}
class Base{
Base(){
method(100);
}
{
System.out.println("base");
}
public void method(int i){
System.out.println("base : " + i);
}
}
class Sub extends Base{
Sub(){
super.method(70);
}
{
System.out.println("sub");
}
public void method(int j){
System.out.println("sub : " + j);
}
}
结果:
base
sub : 100
sub
base : 70
- 父类Base的构造函数中调用method,其实是this.method
- 当前对象是sub,那么method则是被重写的method
四、final关键字
- final:最终的,不可更改的
1、final修饰类
- 表示这个类
不能被继承
,没有子类。提高安全性,提高程序的可读性 - 例如:String类、System类、StringBuffer类
final class Eunuch{//太监类
}
class Son extends Eunuch{//错误
}
2、final修饰方法
- 表示这个方法
不能被子类重写
- 例如:Object类中的getClass()
class Father{
public final void method(){
System.out.println("father");
}
}
class Son extends Father{
public void method(){//错误
System.out.println("son");
}
}
3、final修饰变量
- final修饰某个变量(成员变量或局部变量),一旦赋值,它的值就
不能被修改
,即常量,常量名建议使用大写字母 - 例如:final double MY_PI = 3.14
- 如果某个成员变量用final修饰后,没有set方法,并且必须初始化(可以显式赋值、或在初始化块赋值、实例变量还可以在构造器中赋值)
- 修饰成员变量
public final class Test {
public static int totalNumber = 5;
public final int ID;
public Test() {
ID = ++totalNumber; // 可在构造器中给final修饰的“变量”赋值
}
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.ID);
}
}
- 修饰局部变量
public class TestFinal {
public static void main(String[] args){
final int MIN_SCORE ;
MIN_SCORE = 0;
final int MAX_SCORE = 100;
MAX_SCORE = 200; //非法
}
}
- 错误演示
class A {
private final String INFO = "atguigu"; //声明常量
public void print() {
//The final field A.INFO cannot be assigned
//INFO = "尚硅谷";
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/148564.html