一、static修饰符

  1.1、static变量

在类中,使用static修饰的成员变量,就是静态变量,反之为非静态变量。

静态变量和非静态变量的区别
            静态变量属于类的,"可以"使用类名来访问,非静态变量是属于对象的,"必须"使用对象来访问.

  public class Student{
private static int age;
private double score;
public static void main(String[] args) {
Student s = new Student();
//推荐使用类名访问静态成员
System.out.println(Student.age);
System.out.println(s.age); System.out.println(s.score);
}
}

student.java

静态变量对于类而言在内存中只有一个,能被类的所有实例所共享。实例变量对于类的每个实例都有一份,它们之间互不影响.
            例如:    

          public class Student{
private static int count;
private int num;
public Student() {
count++;
num++;
}
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
Student s3 = new Student();
Student s4 = new Student();
//因为还是在类中,所以可以直接访问私有属性
System.out.println(s1.num);
System.out.println(s2.num);
System.out.println(s3.num);
System.out.println(s4.num); System.out.println(Student.count);
System.out.println(s1.count);
System.out.println(s2.count);
System.out.println(s3.count);
System.out.println(s4.count);
}
}

test

在加载类的过程中为静态变量分配内存,实例变量在创建对象时分配内存
            所以静态变量可以使用类名来直接访问,而不需要使用对象来访问.  

  1.2、static方法

在类中,使用static修饰的成员方法,就是静态方法,反之为非静态方法。

静态方法和非静态方法的区别
            静态方法数属于类的,"可以"使用类名来调用,非静态方法是属于对象的,"必须"使用对象来调用.
        
        静态方法"不可以"直接访问类中的非静态变量和非静态方法,但是"可以"直接访问类中的静态变量和静态方法
            注意:this和super在类中属于非静态的变量.(静态方法中不能使用)
            例如:

      public class Student{
private static int count;
private int num;
public void run(){}
public static void go(){} public static void test(){
//编译通过
System.out.println(count);
go(); //编译报错
System.out.println(num);
run();
} }

非静态方法"可以"直接访问类中的非静态变量和非静态方法,也"可以"直接访问类中的静态变量和静态方法
            例如:

            public class Student{
private static int count;
private int num;
public void run(){}
public static void go(){} public void test(){
//编译通过
System.out.println(count);
go(); //编译通过
System.out.println(num);
run();
} }

思考:为什么静态方法和非静态方法不能直接相互访问?
               
        父类的静态方法可以被子类继承,但是不能被子类重写
            例如:

public class Person {
public static void method() {}
} //编译报错
public class Student extends Person {
public void method(){}
} 例如:
public class Person {
public static void test() {
System.out.println("Person");
}
} //编译通过,但不是重写
public class Student extends Person {
public static void test(){
System.out.println("Student");
}
}
main:
Perosn p = new Student();
p.test();//输出Person
p = new Person();
p.test();//输出Perosn 和非静态方法重写后的效果不一样

test

父类的非静态方法不能被子类重写为静态方法    
            例如:

                public class Person {
public void test() {
System.out.println("Person");
}
} //编译报错
public class Student extends Person {
public static void test(){
System.out.println("Student");
}
}

test

1.3、代码块和静态代码块

1)类中可以编写代码块和静态代码块
        例如:
            public class Person {
                {
                    //代码块(匿名代码块)
                }

static{
                    //静态代码块
                }
            }
        
        2)匿名代码块和静态代码块的执行
            因为没有名字,在程序并不能主动调用这些代码块。

匿名代码块是在创建对象的时候自动执行的,并且在构造器执行之前。同时匿名代码块在每次创建对象的时候都会自动执行.

静态代码块是在类加载完成之后就自动执行,并且只执行一次.

注:每个类在第一次被使用的时候就会被加载,并且一般只会加载一次.

例如:

   public class Person {
{
System.out.println("匿名代码块");
} static{
System.out.println("静态代码块");
}
public Person(){
System.out.println("构造器");
}
}
main:
Student s1 = new Student();
Student s2 = new Student();
Student s3 = new Student();

test

//输出结果:
                    静态代码块
                    匿名代码块
                    构造器
                    匿名代码块
                    构造器
                    匿名代码块
                    构造器

3)匿名代码块和静态代码块的作用
            匿名代码块的作用是给对象的成员变量初始化赋值,但是因为构造器也能完成这项工作,所以匿名代码块使用的并不多。

静态代码块的作用是给类中的静态成员变量初始化赋值。
            例如:

 public class Person {
public static String name;
static{
name = "tom";
}
public Person(){
name = "zs";
}
}
main:
System.out.println(Person.name);//tom

test

注:在构造器中给静态变量赋值,并不能保证能赋值成功,因为构造器是在创建对象的时候才指向,但是静态变量可以不创建对象而直接使用类名来访问.

1.4、创建和初始化对象的过程

Student s = new Student();
            4.1)Student类之前没有进行类加载
                1、类加载,同时初始化类中静态的属性
                2、执行静态代码块
                3、分配内存空间,同时初始化非静态的属性(赋默认值,0/false/null)
                4、调用Student的父类构造器
                5、对Student中的属性进行显示赋值(如果有的话)
                6、执行匿名代码块
                7、执行构造器
                8、返回内存地址

注:子类中非静态属性的显示赋值是在父类构造器执行完之后和子类中的匿名代码块执行之前的时候

例如:

  public class Person{
private String name = "zs";
public Person() {
System.out.println("Person构造器");
print();
}
public void print(){
System.out.println("Person print方法: name = "+name);
}
} public class Student extends Person{
private String name = "tom";
{
System.out.println("Student匿名代码块");
} static{
System.out.println("Student静态代码块");
}
public Student(){
System.out.println("Student构造器");
}
public void print(){
System.out.println("student print方法: name = "+name);
}
public static void main(String[] args) {
new Student();
}
}

test

   //输出结果:
                Student静态代码块
                Person构造器
                student print方法: name = null
                Student匿名代码块
                Student构造器

Student s = new Student();
           4. 2)Student类之前已经进行了类加载
                1.分配内存空间,同时初始化非静态的属性(赋默认值,0/false/null)
                2.调用Student的父类构造器
                3.对Student中的属性进行显示赋值(如果有的话)
                4.执行匿名代码块
                5.执行构造器
                6.返回内存地址

5)静态导入
        静态导入是JDK5.0引入的新特性。
        例如:

 import static java.lang.Math.random;
import static java.lang.Math.PI; public class Test {
public static void main(String[] args) {
//之前是需要Math.random()调用的
System.out.println(random());
System.out.println(PI);
}
}

test

二、final修饰符

2.1、修饰类

用final修饰的类不能被继承,没有子类。
        例如:我们是无法写一个类去继承String类,然后对String类型扩展的,因为API中已经被String类定义为final的了.
        我们也可以定义final修饰的类:

           public final class Action{

             }

             //编译报错
public class Go extends Action{ }

2.2、修饰方法

用final修饰的方法可以被继承,但是不能被子类的重写。
        例如:每个类都是Object类的子类,继承了Object中的众多方法,在子类中可以重写toString方法、equals方法等,但是不能重写getClass方法 wait方法等,因为这些方法都是使用fianl修饰的。
        
        我们也可以定义final修饰的方法:

  public class Person{
public final void print(){}
} //编译报错
public class Student extends Person{
public void print(){ }
}

2.3、修饰变量

用final修饰的变量表示常量,只能被赋一次值.其实使用final修饰的变量也就成了常量了,因为值不会再变了。

1)修饰局部变量:
        例如:

    public class Person{
public void print(final int a){
//编译报错,不能再次赋值,传参的时候已经赋过了
a = 1;
}
} public class Person{
public void print(){
final int a;
a = 1;
//编译报错,不能再次赋值
a = 2;
}
}

2)修饰成员变量:
            非静态成员变量:
                public class Person{
                    private final int a;
                }
                只有一次机会,可以给此变量a赋值的位置:
                    声明的同时赋值
                    匿名代码块中赋值
                    构造器中赋值(类中出现的所有构造器都要写)
                
            静态成员变量:
                public class Person{
                    private static final int a;
                }
                只有一次机会,可以给此变量a赋值的位置:
                    声明的同时赋值
                    静态代码块中赋值
           
    3)修饰引用变量

  main:
final Student s = new Student();
//编译通过
s.setName("tom");
s.setName("zs"); //编译报错,不能修改引用s指向的内存地址
s = new Student();

三、abstract修饰符

abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

  3.1、抽象类和抽象方法的关系

    抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。

  3.2、语法

    public abstract class Action{
              public abstract void doSomething();
          }

     public void doSomething(){...}
          对于这个普通方法来讲:
          "public void doSomething()"这部分是方法的声明
          "{...}"这部分是方法的实现,如果大括号中什么都没写,就叫方法的空实现

   声明类的同时,加上abstract修饰符就是抽象类
          声明方法的时候,加上abstract修饰符,并且去掉方法的大口号,同时结尾加上分号,该方法就是抽象方法。

  3.3、特点及作用

     抽象类,不能使用new关键在来创建对象,它是用来让子类继承的。
          抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
        
          注:子类继承抽象类后,需要实现抽象类中没有实现的抽象方法,否则这个子类也要声明为抽象类。
          例如:
              public abstract class Action{
                  public abstract void doSomething();
              }
              main:
                  //编译报错,抽象类不能new对象
                  Action a = new Action();
           
              //子类继承抽象类
              public class Eat extends Action{
                  //实现父类中没有实现的抽象方法
                  public void doSomething(){
                      //code
                  }
              }

       main:
                  Action a = new Eat();
                  a.doSomething();
              
              注:子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

  3.4、思考

    思考1:抽象类不能new对象,那么抽象类中有没有构造器?
      思考2:抽象类和抽象方法意义(为什么要编写抽象类、抽象方法)
            有抽象方法的抽象类
            无抽象方法的抽象类

    

JavaSE(三)之static、final、abstract修饰符的更多相关文章

  1. Java从入门到放弃——05.修饰符static,final,权限修饰符

    本文目标 static final: 权限修饰符:public,private,protected,缺省 1.static 静态修饰符,被static修饰的变量或者方法会被加载进静态区内存,不需要创建 ...

  2. JavaSE的static、final、abstract修饰符

    static :静态常量,静态方法,静态代码块     静态变量:  静态变量属于类的,使用类名来访问,非静态变量是属于对象的,"必须"使用对象来访问.           注意: ...

  3. 浅析java修饰符之public default protected private static final abstract

    浅析java修饰符之public default protected private static final abstract 一   修饰符的作用:用来定义类.方法或者变量,通常放在语句的最前端 ...

  4. JAVA的abstract修饰符 && 接口interface用法 && 抽象类和interface的差别

    abstract修饰符可以修饰类和方法. (1)abstract修饰类,会使这个类成为一个抽象类,这个类将不能生成对象实例,但可以做为对象变量声明的类型(见后面实例),也就是编译时类型.抽象类就相当于 ...

  5. JavaSE入门学习10:Java修饰符

    Java语言提供了非常多修饰符,主要分为下面两类: 訪问修饰符 非訪问修饰符 修饰符用来定义类.方法或者变量.通常放在语句的最前端.我们通过以下的样例来说明: <span style=" ...

  6. abstract修饰符

    abstract(C# 参考) abstract 修饰符指示所修饰的内容缺少实现或未完全实现. abstract 修饰符可用于类.方法.属性.索引器和事件. 在类声明中使用 abstract 修饰符以 ...

  7. Java基础语法:abstract修饰符

    一.简介 描述: 'abstract'修饰符可以用来修饰方法,也可以修饰类. 如果修饰方法,那么该方法就是抽象方法:如果修饰类,那么该类就是抽象类. 抽象类和抽象方法起到一个框架作用,方便后期扩展的重 ...

  8. abstract修饰符,具体类与抽象类的区别

    abstract修饰符 abstract可以修饰类,表示一个抽象类,注意:抽象类和具体类唯一的区别:类不能创建对象,而具体类是可以创建对象的 1.具体类有构造方法,抽象类也有构造方法 2.具体类可以有 ...

  9. 30 面向对象编程 抽象类 abstract 修饰符可以用来修饰方法也可以修饰类

    抽象类 概念 abstract 修饰符可以用来修饰方法也可以修饰类, 如果修饰方法,那么该方法就是抽象方法: 如果修饰类,那么该类就是抽象类. 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为 ...

随机推荐

  1. SQL Server 服务器主体拥有一个或多个端点无法删除;错误15141

    一.问题描述 当前数据库实例之前已经加入过一个域环境同时也是alwayson集群的一个副本,现在已经退出了以前的域加入一个新域,而且配置的数据库启动服务的域用户和密码和之前的一样.重新使用之前已经存在 ...

  2. Linux下添加源的几种方法

    sudo add-apt-repository  xxxxxxx sudo gedit /etc/apt/sources.list然后把源粘贴进去,保存,最后shell输入sudo apt-get u ...

  3. bzoj 4537 HNOI2016 最小公倍数

    Description 给定一张N个顶点M条边的无向图(顶点编号为1,2,-,n),每条边上带有权值.所有权值都可以分解成2^a*3^b的形式.现在有q个询问,每次询问给定四个参数u.v.a和b,请你 ...

  4. HBase0.98使用ReplicationAdmin管理集群同步

    公司datalink平台负责从各种数据源读取数据并同步到其他的同步或者异构数据源,最近增加的HBase的reader利用到了Hbase的Replication特性. 正常情况下,我们配置HBase的R ...

  5. phpexcel导出成绩表

    效果图如下: 代码如下:代码注释不全,请大家参考phpexcel中文帮助手册 <?php require_once 'PHPExcel.php'; function bfb($n) { retu ...

  6. crm踩坑记(三)

    React 如何同步更新state 由于setState方法是异步的,而通常很多时候在一个生命周期里更新state后需要在另一个生命周期里使用这个state. 下面介绍几个方法 // 1 this.s ...

  7. Spark源码剖析(七):Job触发流程原理与源码剖析

    引言 我们知道在application中每存在一个action操作就会触发一个job,那么spark底层是怎样触发job的呢?接下来我们用一个wordcount程序来剖析一下job的触发机制. 解析w ...

  8. python csv模块的reader是一个迭代器,无法多次迭代

    在一个项目中,我需要多次遍历一个文本,该文本我是用csv.reader读取的.但后来发现,本文只对第一次循环有用,而之后的循环均为空白.经过排错后,我确定问题就出现在csv.reader()这一步.之 ...

  9. 本机向windows服务器传输文件的三种方法

    闲来无事,在腾讯云上申请了一个免费的服务器,想将自己写的网页发布到服务器上,服务器的申请很简单,百度搜索 腾讯云 ,然后新人第一次注册能申请到免费一个月的云主机,虽然配置不怎么高,但是还是能用的,这是 ...

  10. Linux如何让进程在后台运行的三种方法详解

    问题分析: 我们知道,当用户注销(logout)或者网络断开时,终端会收到 HUP(hangup)信号从而关闭其所有子进程.因此,我们的解决办法就有两种途径:要么让进程忽略 HUP 信号,要么让进程运 ...