对static的印象一直都是一句话:当加上该属性后,类不可被继承,方法不可被覆盖,属性不可被修改。然而却没有怎么实战过,这次通过一些代码上的优化发现了static的作用和小技巧,也加深了对它的理解。

1.static关键字修饰成员方法       

class Team{
    public Team(String msg) {
        System.out.println(msg);
    }
}

public class Person {

    Team team1 = new Team("team1成员变量初始化");
    static Team team2 = new Team("static成员team2成员变量初始化");
    
    public Person(String msg) {
        System.out.println(msg);
    }
    
    Team team3 = new Team("team3成员变量初始化");
    static Team team4 = new Team("static成员team4成员变量初始化");
    
    public static void funStatic() {
        System.out.println("static修饰的funStatic方法");
    }
    
    public static void main(String[] args) {
        Person p1 = new Person("p1初始化");
    }

	
	
	
      static成员team2成员变量初始化
      static成员team4成员变量初始化
      static修饰的funStatic方法
      team1成员变量初始化
      team3成员变量初始化
      p1初始化
}

当大家执行后可能会发现一个问题,Java代码难道不是逐行执行的吗?呵呵,这就是static关键字的作用了。相比于修饰成员属性,修饰成员方法对于数据的存储上面并没有多大的变化,因为我们从上面可以看出,方法本来就是存放在类的定义当中的。可以使用"类名.方法名"的方式操作方法,避免了先要new出对象的繁琐和资源消耗。但是对于入行不久的小白lz来说,这个所谓的资源消耗还不是特别理解。

至于为什么使用"类名.方法名"的方式来操作方法,其实就相当于定义了一个全局的函数(只要导入该类所在的包即可)。不过它也有使用的局限,一个static修饰的类中,不能使用非static修饰的成员变量和方法,这很好理解,因为static修饰的方法是属于类的,如果去直接使用对象的成员变量,它会不知所措(不知该使用哪一个对象的属性)。

2.static静态块

我的理解是,在static静态块中的代码,在加载类的时候就首先执行。比如这样一个场景,不在数据库建表,但是需要保存一些自定义的状态,这个时候就可以采用static静态块,每次调用该类时,会先加载静态块,静态块会去读取你的json文件或者其他的文件,将之加载到内存中便于你的调用。

实际上,static修饰的成员的初始化可以更早的进行static修饰的类成员,在程序运行过程中,只需要初始化一次即可,不会进行多次的初始化。

private  static  Map<String,String> sba;
    private  static   Map<String,String> abs;
    private  static   Map<String,String> notify;

    static {

        try {
            List<Map<String,String>> list =  new ArrayList<>();
            List<Map<String,String>> notifylist =  new ArrayList<>();
            File jsonFile = ResourceUtils.getFile("classpath:city.json");
            String jsonSting  = FileUtils.readFileToString(jsonFile);
            JSONObject json = JSONObject.parseObject(jsonSting);
            //1,加载供应商
            JSONArray arrayCity = JSONArray.parseArray(json.getString("cityCode"));
            for (int i=0;i<arrayCity.size();i++){
                Map<String,String> maps = new TreeMap<>();
                JSONObject jsonCity = JSONObject.parseObject(arrayCity.get(i).toString());
                maps.put("apiBizCode",jsonCity.getString("apiBizCode"));
                maps.put("supplierBizCode",jsonCity.getString("supplierBizCode"));
                maps.put("supplierCode",jsonCity.getString("supplierCode"));
                list.add(maps);
            }
            //建立 供应商编码 供应商业务 和api业务关系
            sba = new HashMap<>();

            //建议 编码供 编码 和供应商编码关系
            abs = new HashMap<>();

            //建议 供应商状态 供应商编码 和api编码关系
            notify = new HashMap<>();

            for(int i=0;i<list.size(); i++){
                Map<String,String> temp = list.get(i);
                String apiBizCode = temp.get("apiBizCode");
                String supplierBizCode =  temp.get("supplierBizCode");
                String supplierCode = temp.get("supplierCode");
                sba.put(supplierCode+"_"+supplierBizCode,apiBizCode);
                abs.put(supplierCode+"_"+apiBizCode,supplierBizCode);
            }
            //2,加载回调订单状态
            JSONArray arrayStauts = JSONArray.parseArray(json.getString("notifyStatus"));
            for (int i=0;i<arrayStauts.size();i++){
                Map<String,String> maps = new TreeMap<>();
                JSONObject jsonCity = JSONObject.parseObject(arrayStauts.get(i).toString());
                maps.put("apiNotifyStatus",jsonCity.getString("apiNotifyStatus"));
                maps.put("supplierNotifyStatus",jsonCity.getString("supplierNotifyStatus"));
                maps.put("supplierCode",jsonCity.getString("supplierCode"));
                notifylist.add(maps);
            }

            for(int i=0;i<notifylist.size(); i++){
                Map<String,String> temp = notifylist.get(i);
                String apiNotifyStatus = temp.get("apiNotifyStatus");
                String supplierNotifyStatus =  temp.get("supplierNotifyStatus");
                String supplierCode = temp.get("supplierCode");
                //拿到api状态下的供应商编码和状态
                notify.put(supplierCode+"_"+supplierNotifyStatus,apiNotifyStatus);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

上面的代码是去读取相应的json文件,然后解析封装到相应的map数组中,再定义相应的方法进行调用即可。这种方式也是可以减轻内存消耗,毕竟对数据库的依赖降低了一点。

3.static静态导包

一句话定义,在一个类中定义了一个static关键字修饰的静态方法,在另外一个类中直接调用这个方法(不用类名.方法名的形式),那么它会在导入相应包的路径前加入相应的static选项。感觉这个用的不多,稍微提及一下。

4.对于static关键字的一些问题

  4.1是否可以从一个static方法内部发出对非static方法的调用?

  答案是不可以,既然static静态代码块是类加载即执行,那么它极有可能还没有创建任何的实例对象,如果调用非static方法,那么非static方法的对象关联到哪个上面呢?所以这样做是不可行的。

  4.2static关键字是否可以大规模应用?

  我觉得是因程序而异,就像在static代码块中就不能使用this,super这些关键字,并且在单例模式中运用static,有大概率会出现线程锁的现象,所以要仔细考虑应用。

总结一下开始说的那一句话:

被static修饰:

类不可被继承:通常是不可以直接用static修饰类名,只能说用static修饰匿名内部类然后进行调用,至于是否可以继承的问题,

                      我理解的是可以,但是要看定义的位置。

方法不可被覆盖:你可以定义一个static修饰的方法名,就算另外起一个这个方法名的方法也是可以的,因为修饰类型不同。

public static void amdintst() {
		
	}
	
	public void amdmintst() {
		
	}



属性不可被修改:就算在子类中调用了父类的方法,子类不管怎么做修改父类都不会因此而产生任何改变。