【Java基础】静态类

来源:互联网 发布:吴京直男癌 知乎 编辑:程序博客网 时间:2024/06/06 05:32

       前几天在交流IOC的时候,提到了静态类的写法,我的一个误区静态类 长这个样子:

public static class StaticClass{     //TODO}
      然鹅,“事与愿违”,静态类直接在class前加入"static"在Java中是一种错误的写法,在北京工作的时候由于写过工具类就天真的认为java的世界中也是酱紫,那就正好整理下在java语言中静态类如何玩吧。


      一、分类

     (1)外部静态类

public class StaticClass1{     //静态成员变量     //静态成员方法}

     (2)内部静态类

class OuterClass{    //普通成员变量    //静态成员变量    static class InnerStaticClass{          //静态或非静态成员变量          //静态或非静态成员方法     }} 


      二、实例举例

      (1)内部静态类(外部就不予展示,很常见)

package StaticClass;class Outer {    private String name;    private int age;    public static class Builder {        private String name;        private int age;        public Builder(int age) {            this.age = age;        }        public Builder withName(String name) {            this.name = name;            return this;        }        public Builder withAge(int age) {            this.age = age;            return this;        }        public Outer build() {            return new Outer(this);        }    }    private Outer(Builder b) {        this.age = b.age;        this.name = b.name;    }}public class StaticClass1 {public static void main(String[] args) {Outer outer = getOuter();System.out.println(outer.toString());}public static Outer getOuter(){    Outer outer = new Outer.Builder(25).withName("Vincent").build();    return outer;}}
       参考上述代码,如果一个类被声明为static,只有一种情况,就是静态内部类。(Attention:把上述这个例子搞清楚了,静态内部类就没有问题了。)
       

       同时,比较静态内部类和普通内部类有几点不同:

      (1)静态内部类跟静态方法一样,只能访问静态的成员变量和方法,不能访问非静态的方法和属性,但是普通内部类可以访问任意外部类的成员变量和方法。

      (2)静态内部类可以声明普通成员变量和方法,而普通内部类不能声明static成员变量和方法。


     三、静态类的特点

       谈及静态类的特点,也是为什么要使用静态类的原因

      (1)静态类的数据在全局是唯一的,一改都改。如果你想要处理的东西是整个程序中唯一的,弄成静态是个好方法。 非静态的东西你修改以后只是修改了他自己的数据,但是不会影响其他同类对象的数据。

        参考下午我设计的一个demo:

public class StaticClass2 {public static void main(String[] args){//第一次调用StaticClass2中的值aSystem.out.println("StaticClass2中a的值为: " + TestStaticClass.a);//通过另外一个类来修改StaticClass2中a的值TestStaticClass1 testStaticClass1 = new TestStaticClass1();testStaticClass1.test();//第二次调用StaticClass2中的值aSystem.out.println("StaticClass2中a的值为: " + TestStaticClass.a);}}class TestStaticClass{static int a = 3;static int b;static{System.out.println("inti data2");b = a * 3;}}class TestStaticClass1{public void test(){TestStaticClass.a = 6;}}
       执行结果如图:

      

      从这个输出结果看,StaticClass2中的静态成员变量a的值被其他类的对象修改之后,main方法再去拿一次,值已经变掉了。。。。


      (2)引用方便,直接通过“类名.静态方法名”或者“类名.静态变量名”就可以使用并修改期属性值,不用通过get()和set()方法来做。


     四、对比“对象实例化”与“静态类的静态块”

        前些天在复习JVM的时候,学习了类的加载机制,其中在“初始化”的阶段,有主动和被动之区别,对于静态的成员变量、静态块就是主动的初始化。但是当时没有理解“静态块”和实例化new初始化之间的关系,在这里做个总结,看一个demo:

public class StaticClass3 {public static void main(String[] ars){     A ab = new B(); //记为A。执行到此处,结果是:     ab = new B(); //记为B。执行到此处,结果是:      B bb=new B();//记为C。执行到此处,结果是:   }}class A {static {System.out.print("1");}public A() {System.out.print("2");}}class B extends A {static {System.out.print("a");}public B() {System.out.print("b");}}

      可以执行一下main()方法,看看会有什么样的结果,在main()中是有三行代码的,

     (1)“A ab = new B();”

     (2)“ab = new B();”

     (3)“B bb = new B();”

      我操作的方法是先都注释掉,然后一行一行的放开注释,打印的结果是这样的:

      "1a2b","1a2b2b","1a2b2b2b"

       

       如上的操作结果,说明其实多次new实例化的过程中,satatic{}块中的代码,仅仅被执行了一次,然而new执行的构造方法的调用,是每次都运行的。同时可以分析得出,方法的调用顺序是:“父类静态代码块 > 子类静态代码块 > 父类构造函数 > 子类构造函数”。

       总结:

      (1)静态有限执行并且父类有限执行。

      (2)静态代码是在JVM加载类的时候执行的,且仅仅执行一次;构造方法是每次new都会执行。


     四、应用

     (1)封装工具类

       每一个应用程序中都有共性的功能,可以将这些功能进行抽取,封装,结合上面的特性,在调用的时候就不用每次new实例化,直接"类名.属性值"或者“类名.方法名”就ok了。

       我在北京工作时候,我们组封装的一个工具类(虽然是C#,但是原理一样)

using System;using System.Collections.Generic;using System.Text;using VRLeCom.Commons;using VRLeCom.Server;using VRLeCom.Service;namespace VRLeCom.Handle{    public class CommandHanle    {        /// <summary>        /// 解析命令        /// </summary>        /// <param name="data"></param>        /// <param name="actionid"></param>        /// <returns></returns>        public static string PhraseCMD(byte[] data, out ushort actionid)        {            byte versionID = data[0];            actionid = 0;            switch (versionID)            {                case 1:                    {                        try                        {                            byte[] b = new byte[data.Length - 1];                            Array.Copy(data, 1, b, 0, b.Length);                            //data.CopyTo(b, 1);                            var model = Encoding.UTF8.GetString(b).Deserialize<Dictionary<string, object>>();                            if (model.ContainsKey("actid") && model.ContainsKey("param"))                            {                                actionid = ushort.Parse(model["actid"].ToString());                                var c = model["param"] == null ? "" : model["param"].ToString();                                return c;                                //typeof(T).InvokeMember(action, System.Reflection.BindingFlags.InvokeMethod, null, null, )                            }                        }                        catch (Exception ex)                        {                            Log.Write(nameof(CommandHanle), $"指令分析失败:{ex.Message}", LogType.System, LogLevel.Crash);                            //Console.WriteLine("指令分析失败 :" + ex.Message);                        }                        break;                    }                default:                    break;            }            return null;        }        /// <summary>        /// 生成命令        /// </summary>        /// <param name="versionID"></param>        /// <param name="obj"></param>        /// <param name="actionid"></param>        /// <returns></returns>        public static byte[] GeneratCMD(byte versionID, object obj, ushort actionid)        {            byte[] data = null;            switch (versionID)            {                case 1:                    {                        try                        {                            string content = new { actid = actionid, param = obj }.Serialize();                            byte[] c = Encoding.UTF8.GetBytes(content);                            data = new byte[c.Length + 1];                            data[0] = versionID;                            Array.Copy(c, 0, data, 1, c.Length);                        }                        catch (Exception ex)                        {                            Console.WriteLine("指令生成失败 : " + ex.Message);                            return null;                        }                        break;                    }                default:                    break;            }            return data;        }        /// <summary>        /// 解析Android,IOS端命令        /// </summary>        /// <param name="data"></param>        /// <param name="actionid"></param>        /// <returns></returns>        public static string PhrasePOCMD(byte[] data, out ushort actionid)        {            byte versionID = data[0];            actionid = 0;            switch (versionID)            {                case 1:                    {                        try                        {                            byte[] b = new byte[data.Length - 3];                            byte[] action = new byte[2];                            Array.Copy(data, 1, action, 0, 2);                            Array.Copy(data, 3, b, 0, b.Length);                            actionid = BitConverter.ToUInt16(action, 0);                            string ccc = Encoding.UTF8.GetString(b);                            return ccc;                        }                        catch (Exception ex)                        {                            Log.Write(nameof(CommandHanle), $"指令分析失败:{ex.Message}", LogType.System, LogLevel.Crash);                            //Console.WriteLine("指令分析失败 :" + ex.Message);                        }                        break;                    }                default:                    break;            }            return null;        }                 /// <summary>        /// 生成Android,IOS命令        /// </summary>        /// <param name="versionID"></param>        /// <param name="obj"></param>        /// <param name="actionid"></param>        /// <returns></returns>        public static byte[] GeneratPOCMD(byte versionID, object obj, ushort actionid)        {            byte[] data = null;            switch (versionID)            {                case 1:                    {                        try                        {                            string content = obj.Serialize();                            byte[] c = Encoding.UTF8.GetBytes(content);                            data = new byte[c.Length + 3];                            data[0] = versionID;                            byte[] testByte = BitConverter.GetBytes(actionid);                            data[1] = testByte[0];                            data[2] = testByte[1];                            //data[1] = (byte)((0xff00 & actionid) >> 8);                            //data[2] = (byte)(0xff & actionid);                            Array.Copy(c, 0, data, 3, c.Length);                        }                        catch (Exception ex)                        {                            Console.WriteLine("指令生成失败 : " + ex.Message);                            return null;                        }                        break;                    }                default:                    break;            }            return data;        }        /// <summary>        /// 发送命令,有返回值        /// 此方法应尽量避免使用,因为是阻塞调用,是造成卡死状态可能原因之一        /// </summary>        /// <param name="actionid"></param>        /// <param name="obj"></param>        /// <param name="proxy"></param>        /// <returns></returns>        public static byte[] ReqCMD_N(ushort actionid, object obj, ServerClient proxy)        {            byte[] response = null;            byte[] cmd = null;            try            {                cmd = GeneratCMD(Cmds.CMDVersionId, obj, actionid);                response = ServerHelper.TryAction(() =>                {                    return proxy.SendOrder_N(cmd);                });            }            catch (Exception ex)            {                if (actionid != Cmds.BeatBrother)                    Log.Write("发送命令", $"发送命令:{actionid}异常:{ex.Message}", LogType.System, LogLevel.Error);            }            return response;        }        /// <summary>        /// 发送命令,无返回值,非阻塞调用        /// 信息一旦到达目标端,则返回true,不保证目标端的命令可以成功执行,如果需要返回结果,则目标端后续要回调自己        /// </summary>        /// <param name="actionid"></param>        /// <param name="obj"></param>        /// <param name="proxy"></param>        /// <returns></returns>        public static bool ReqCMD(ushort actionid, object obj, ServerClient proxy)        {            byte[] cmd = null;            try            {                cmd = GeneratCMD(Cmds.CMDVersionId, obj, actionid);                return ServerHelper.TryAction(() =>                {                    proxy.SendOrder(cmd);                });            }            catch (Exception ex)            {                if (actionid != Cmds.BeatBrother)                    Log.Write("发送命令", $"发送命令:{actionid}异常:{ex.Message}", LogType.System, LogLevel.Error);                return false;            }        }        /// <summary>        /// 同步调用S端接口,有返回值        /// </summary>        /// <param name="actionId"></param>        /// <param name="obj"></param>        /// <returns></returns>        public static byte[] ReqCMD_N_S(ushort actionId, object obj)        {            if (Cmds.TransType == TransferType.WCFTCP)                return ReqCMD_N(actionId, obj, ServerHelper.ControlerProxy);            else                return TCPReqCMD_N(actionId, obj, ServerHelper.TCPControlerProxy);        }        /// <summary>        /// 异步调用S端接口        /// </summary>        /// <param name="actionId"></param>        /// <param name="obj"></param>        /// <returns></returns>        public static bool ReqCMD_S(ushort actionId, object obj)        {            if (Cmds.TransType == TransferType.WCFTCP)                return ReqCMD(actionId, obj, ServerHelper.ControlerProxy);            else                return TCPReqCMD(actionId, obj, ServerHelper.TCPControlerProxy);        }        /// <summary>        /// 同步调用兄弟程序接口        /// </summary>        /// <param name="actionId"></param>        /// <param name="obj"></param>        /// <returns></returns>        public static byte[] ReqCMD_N_Brother(ushort actionId, object obj)        {            if (Cmds.TransType == TransferType.WCFTCP)                return ReqCMD_N(actionId, obj, ServerHelper.BrotherProxy);            else                return TCPReqCMD_N(actionId, obj, ServerHelper.TCPBrotherProxy);        }        /// <summary>        ///         /// </summary>        /// <param name="actionId"></param>        /// <param name="obj"></param>        public static void ReqCMD_Brother(ushort actionId, object obj)        {            if (Cmds.TransType == TransferType.WCFTCP)                ReqCMD(actionId, obj, ServerHelper.BrotherProxy);            else                TCPReqCMD_N(actionId, obj, ServerHelper.TCPBrotherProxy);        }        #region TCPClient        public static byte[] TCPReqCMD_N(ushort actionid, object obj, TCPProxy proxy)        {            byte[] response = null;            byte[] cmd = null;            try            {                cmd = GeneratCMD(Cmds.CMDVersionId, obj, actionid);                response = ServerHelper.TryAction(() =>                {                    return proxy.SentOrder(cmd, false);                });            }            catch (Exception ex)            {                if (actionid != Cmds.BeatBrother)                    Log.Write("发送命令", $"发送命令:{actionid}异常:{ex.Message}", LogType.System, LogLevel.Error);            }            return response;        }        public static bool TCPReqCMD(ushort actionid, object obj, TCPProxy proxy)        {            byte[] cmd = null;            try            {                cmd = GeneratCMD(Cmds.CMDVersionId, obj, actionid);                return ServerHelper.TryAction(() =>                {                    proxy.SentOrder(cmd, true);                });            }            catch            {                return false;            }        }        #endregion    }}
        如上所示,就是静态类最常用的一点了,对于我暂且理解到这个层次也就ok了。
        最后有一点,如果为了保证工具类不被别人初始化,强制工具类不能建立对象,可以将其构造函数私有化,就Ok了,这就严谨多了。

        That's all. (吃饭去了,饿死了)










       

原创粉丝点击