一、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. springboot 入门四-时间类型处理

    springboot 自带了jackson来处理时间,但不支持jdk8 LocalDate.LocalDateTime的转换. 对于Calendar.Date二种日期,转换方式有二种: 一.统一app ...

  2. Pipeline in scala——给scala添加管道操作

     linux系统中管道这一功能相信大家肯定使用过,比如现在想找到用户目录下文件名包含db的所有文件,ls ~的结果,作为grep db的参数: ➜ ~ ls ~ | grep db kv.mv.db ...

  3. nginx搭建rtmp协议流媒体服务器总结

    最近在 ubuntu12.04+wdlinux(centos)上搭建了一个rtmp服务器,感觉还挺麻烦的,所以记录下. 大部分都是参考网络上的资料. 前提: 在linux下某个目录中新建一个nginx ...

  4. js代码细嚼慢咽

    全局变量的梗 例1: 对于var 的理解:将该变量声明在当前的作用域中,或者说执行上下文中. function add() { result = 3; //result变量即是隐喻全局变量 } add ...

  5. Ubuntu配置Django+ Apache2+ mysql

    # 我的Ubuntu上自带的python3.5,所以安装一下 python3.6sudo add-apt-repository ppa:jonathonf/python-3.6sudo apt-get ...

  6. Java 浅析Thread.join()

    概要 本文分为三部分对 Thread.join() 进行分析: 1. join() 的示例和作用 2. join() 源码分析 3. 对网上其他分析 join() 的文章提出疑问 1. join() ...

  7. python学习中的一些“坑”

    一.交互列表元素时,需要注意的坑. 例如: array=[4,5,9,8,10,8,4,0,3,4]  最大的值与第一个元素交换,最小的值与最后一个元素交换 # -*- coding: UTF-8 - ...

  8. ExpandableListView的完美实现,JSON数据源,右边自定义图片

    转载请标明出处: http://www.cnblogs.com/dingxiansen/p/8194669.html 本文出自:丁先森-博客园 最近在项目中要使用ExpandableListView来 ...

  9. [编织消息框架][传输协议]sctp

    OSI(Open System Interconnect),即开放式系统互联. 一般都叫OSI参考模型,是ISO(国际标准化组织)组织在1985年研究的网络互联模型. 该体系结构标准定义了网络互连的七 ...

  10. Anaconda系统中管理程序包(Package)

    列出所有已安装的程序包 conda list 在已安装的程序包中查找某个特定的程序包 conda search package-name 安装程序包 conda install beautiful-s ...