zoukankan      html  css  js  c++  java
  • Java 类加载与static+工厂模式+单例模式详解

    一.类加载

    当jvm去运行一个类时,会先加载该类,把该类在硬盘上字节码加载到jvm的内存。
    java HelloWorld
    >字节码会被加载到代码段中
    >加载过程中会有一些静态的常量,这部分会事先存放到数据段中

    类加载与static的关系
    类加载会去初始化static修饰的变量
    类加载会去执行静态的代码块

    类加载实际上由类加载器加载,这个加载器是ClassLoader

     

    二.static

    (1)修饰变量

    用static修饰变量,该变量成为类变量,用于给属于该类的所有对象共享。
    1 内存位置 - 数据段
    2 生命周期 - 从类加载开始就有了(实例变量生命周期从创建对象开始),static变量要比实例变量更早出现
    3 使用范围 - 实例变量只能是拥有它的对象才能使用,类变量是所有对象共享

    如何访问类变量
    1)通过对象引用
    Person p = new Person();
    System.out.println(p.count);
    2)通过类名(常用的方式)
    System.out.println(Person.count);

     

    (2)修饰方法

    static修饰方法,该方法成为了类方法,通过类名访问。

    (3)静态方法的使用场合

    1 我们的工具类一般都不需要创建对象就可以调用它的方法,这些工具类的方法都声明为static,这样子就直接通过类名就能够调用了
    /**
     * 工具类
     */
    class JdbcUtils{
      public static Connection getConnection(){
         return null;
      }
      public static void close(Connection conn){   
      }
    }
    
    2 在一些类似枚举场合(季节)
    /**
     * 季节
     * 一般枚举变量用大写
     * 1)固定个数
     * 2)不变的
     * 3)个数比较少
     */
    class Season{
     public static final Season SPING = new Season("春天");
     public static final Season SUMMER = new Season("夏天");
     public static final Season AUTUMN = new Season("秋天");
     public static final Season WINTER = new Season("冬天");
     private String season;
     /**
     * 构造方法私有化
     * @param season
     */
     private Season(String season){
     this.season = season;
     }
     public String getSeason(){
     return season;
     }
    }
    enum Seasons{
      SPING("春天"),
      SUMMER("夏天"),
      AUTUMN("秋天"),
      WINTER("冬天");
      private String season;
      private Seasons(String season){
         this.season = season;
      }
      public String getSeason(){
         return season;
      }
    }
    
    3 单例模式
     一个类只有一个对象(饿汉式,懒汉式)
    /**
     * 饿汉式,类加载就直接创建出对象,有可能造成启动慢
     */
    class Singleton{
     private static Singleton instance = new Singleton();
     // 构造方法私有化
     private Singleton(){
     }
     public static Singleton getInstance(){
      return instance;
     }
    }
    /**
     * 懒汉式
     */
    class Singleton{
     private static Singleton instance =null;
     // 构造方法私有化
     private Singleton(){
     }
     public static Singleton getInstance(){
      if(null==instance){
        instance = new Singleton();
      }
      return instance;
     }
    }
    
    4 工厂模式(静态)
     屏蔽细节
    /**
     * 简单工厂
     */
    class CarFactory{
     public static Car createCar(){
        Car c = new Car();
        c.color = "red";
        c.driver = "9缸";
        c.decoration = "真皮";
        return c;
     }
    }
    class Car {
     public String color;
     public String driver;
     public String decoration;
     public void run(){
        System.out.println(color+"的汽车在奔跑");
     }
    }
    
    
     

     

     (4)语法限制

    1 不能在静态的方法内部(静态的上下文)访问非静态的成员(属性和方法),除非创建一个对象,用对象名.实例方法名来调用。
    但非静态的方法可以直接访问静态的变量和方法


    public class TestStatic3{
    int i = 8;//实例变量,对象变量
    public static void main(String[] args){
    //System.out.println(i);//编译出错,没有对象哪来的实例变量
    System.out.println(new TestStatic3().i);
    }
    }



    2 静态方法内部没有this(本实例)和super(父实例)引用
    3 静态方法之间可以重载
    4 静态的方法可以被继承,但是不能重写。如果父类中有一个静态的方法,子类也有一个与其方法名,参数类型,参数个数都一样的方法,并且也有static关键字修饰,那么该子类的方法会把原来继承过来的父类的方法隐藏,而不是重写。
    5 静态的方法不能被非1静态的方法覆盖
    6 非静态的方法不能被静态的方法覆盖

    http://blog.csdn.net/ycb1689/article/details/17163273
    父类的普通方法可以被继承和重写,不多作解释,如果子类继承父类,而且子类没有重写父类的方法,但是子类会有从父类继承过来的方法。
    静态的方法可以被继承,但是不能重写。如果父类中有一个静态的方法,子类也有一个与其方法名,参数类型,参数个数都一样的方法,并且也有static关键字修饰,那么该子类的方法会把原来继承过来的父类的方法隐藏,而不是重写。通俗的讲就是父类的方法和子类的方法是两个没有关系的方法,具体调用哪一个方法是看是哪个对象的引用;这种父子类方法也不在存在多态的性质。《Java编程思想》中这样提到“只有普通的方法调用可以是多态的”。

    5)main方法


    public static void main(String[] args){

    }

    这是程序入口方法,这是一个固定方法,只有args这个变量可以变。

    为什么main必须是static?
    jvm去运行一个类时,首先会加载这个类,然后运行main方法,此时是没有对象创建出来的。这时
    main只有是static修饰才能去执行

    main方法的参数是用来干吗的?
    用来接收jvm的程序参数。我们运行一个类时,可以传一个参数值进去

    (6)static的优劣

    static的优势:
    1)不用创建对象,节省空间
    2)使用时通过类名调用,方便

    static的劣势
    没有办法使用多态

    三.静态代码块

    1 有何用
    用来初始化静态的变量,例如jdbc中初始驱动类,url....

    2 运行的时机
    类加载的时候去运行
    静态代码块和静态变量的初始化是同样的时机,是按照它们出现先后顺序去执行

    四.实例代码块

    实例代码块用来初始化实例变量
    {
    i = 9;
    System.out.println("------------实例代码块-------");
    }

    运行时机
    构造方法之前,与实例变量显示初始化是平级的,谁先谁后看它们在类中出现的顺序

    五.对象创建过程

    1 先加载类(先加载父类)
    2 执行静态代码块或者初始化静态的变量
    3 分配堆内存空间
    4 默认初始化父类属性(实例变量)
    5 执行实例代码块或显式初始化父类属性(实例变量)
    6 调用父类的构造方法完成。
    7 默认初始化自己类属性(实例变量)
    8 显式初始化自己类属性(实例变量)
    9 调用自己类的构造方法
    总结:先执行静态属性和静态代码块,再执行属性,最后执行构造方法。

     


  • 相关阅读:
    android EditText 软键盘 一些总结
    Activity的4种加载模式最佳解答及Intent常用标识
    Android App监听软键盘按键的三种方式
    解决ScrollView下嵌套ListView、GridView显示不全的问题(冲突)
    Android使用WindowManager实现悬浮窗口
    android 设置软键盘默认为26位软键盘
    android:configChanges属性总结
    空腹吃香蕉对身体好吗?哪些水果不宜空腹吃
    冒泡排序,选择排序,二分法
    Android:内存优化的一些总结
  • 原文地址:https://www.cnblogs.com/Transkai/p/10351083.html
Copyright © 2011-2022 走看看