Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式

    01-面向对象(Static关键字)

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第1张图片

        我们发现一个问题,这两个对象中有相同的属性值,每个对象的内容都是一样的,这样会比较耗费内存空间,我们能不能把相同的部分取出来放在一个地方,谁要用就拿过去用,没有必要每个对象都存一份。

        这个时候就需要给这个变量前面加上static。

        静态:static。

        用法:是一个修饰符,用于修饰成员(成员变量,成员函数)。

        当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用。调用方式为:类名.静态成员。

        被静态修饰后,country就不再在堆内存当中了。

        静态修饰的变量是被对象所共享的。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第2张图片
类名调用

        类名调用好方便!那干脆把所有属性都静态好啦,都可以类名调用!比如姓名什么的。

        啊?姓名?emmm...好像有点问题诶。

        国籍大家都是一样的,都是中国人,但是姓名却是各自不同的。

        我们要明白,事物当中哪些属性是共享的,哪些是特有的。特有的一定要跟着对象来存储。

        static特点:

        1,随着类的加载而加载。

                也就是说,静态会随着类的消失而消失。说明它的生命周期最长。

                因此,也不建议把所有有的没的的变量都定义成静态,这样即使对象没了,这些变量还在内存中,是对内存的一种消耗。所以定义静态之前一定要想好,这个东西是不是需要被所有对象所共享?是,定义静态。不是,就别定义静态啦!

        2,优先于对象存在。

                明确一点:静态是先存在,对象是后存在。

                即使没有对象存在,这个静态成员也已经存在了。(没有对象存在的时候,也无法通过对象来调用这个成员变量,就只能通过类来调用,所以就有第四条所说的,可以直接被类名调用)

        3,被所有对象所共享。

        4,可以直接被类名调用。

        实例变量和类变量的区别:

        1,存放位置。

                类变量随着类的加载而存在于方法区中。

                实例变量随着对象的建立而存在于堆内存中。

        2,生命周期。

                类变量声明周期最长,随着类的消失而消失。

                实例变量生命周期随着对象的消失而消失。

        静态使用注意事项:

        1,静态方法只能访问静态成员。成员包括方法和变量。(如果还没有建立对象,这个时候就没办法访问非静态成员啦,因为它们还不存在呢)

              非静态方法既可以访问静态也可以访问非静态。

        2,静态方法中不可以定义this,super关键字。

              因为静态优先于对象存在。所以静态方法中不可以出现this。

        3,主函数是静态的。

        静态有利有弊:

        利:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。

        可以直接被类名调用。

        弊:生命周期过长。

        访问出现局限性。(静态虽好,只能访问静态)


        介绍一个新的内存空间,方法区:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第3张图片
方法区

        静态变量既不在堆中也不在栈中,而是在方法区中。方法区中同时也存放着该类的各种方法~(细心的我发现了之前堆内存中都木有画方法,嘻嘻)

    02-面向对象(main函数)

        为什么主函数是静态的呢?

        我们这节来讲一讲。

        public static void main(String[] args)

        主函数:是一个特殊的函数。作为程序的入口,可以被jvm调用。

        主函数的定义:

        public:代表着该函数访问权限是最大的。

        static:代表主函数随着类的加载就已经存在了。

        void:主函数没有具体的返回值。

        main:不是关键字,但是是一个特殊的单词,可以被jvm识别。

        (String[] args):函数的参数,参数类型是一个数组,该数组中的元素是字符串。也就是说,是存储字符串类型的数组。

        主函数是固定格式的:jvm识别。        

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第4张图片
主函数格式

        args的原型是arguments,刚开始是这样写的,因为比较长,所以后来简写成args。

         那么,虚拟机到底传入了什么呢?

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第5张图片
String[] args里面是什么呢?
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第6张图片

        因此,jvm在调用主函数时,传入的是new String[0];

        能不能打印角标为0的元素呢?

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第7张图片

        越界啦!

        刚刚那个0的意思是长度是0,是有0个元素,而不是里面存的东西是0。而0角标代表的是第一个元素。

        javac启动了编译器,java启动了底层虚拟机。要使用哪个类,就将这个类的类名作为参数传入虚拟机。传进去的同时,它会调用这个类的main方法,我们试着在后面再加一些主函数的参数:emmm...haha hehe heihei。

        虚拟机做了一件事,自动的将类名后面所跟的数据,存入了数组当中。

        不信看一看~

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第8张图片

        不信再看一看~

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第9张图片

        再玩点更有意思的:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第10张图片

        这两个类是独立的,虚拟机可以执行类1主函数,也可以执行类2主函数。我们用虚拟机执行其中一个类的主函数,这个的主函数也可以调用另一个类的主函数。

    03-面向对象(静态什么时候使用)

        什么时候使用静态?

        要从两方面下手:

        因为静态修饰的内容有成员变量和函数。

        什么时候定义静态变量(类变量)呢?

        当对象中出现共享数据时,该数据被静态所修饰。(比如姓名就不是共享数据,他们只是共享属性,都有这个属性,但每个人的姓名值是不一样的。)

        对象中的特有数据要定义成非静态存在于堆内存中。

        什么时候定义静态函数呢?

        当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。

        比如:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第11张图片

        show方法改成静态后直接类名调用就OK啦:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第12张图片

    04-面向对象(静态的应用-工具类)


Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第13张图片

        这个例子中,将获取最大值的功能封装在一个函数中,提高了代码的复用性。

        但是,不只这个类会用到获取最大值的功能,其他类也会用到。我们就可以把这个功能抽取出来,封装在一个类中,这个类想什么时候用就什么时候用。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第14张图片
功能的抽取

        静态的应用        

        每一个应用程序中都有共性的功能,可以将这些功能进行抽取,独立封装,以便复用。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第15张图片
文件名:ArrayTool.java
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第16张图片
文件名:ArrayToolDemo.java
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第17张图片
编译过程
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第18张图片

        第一次编译后,当前目录中会产生一个ArrayTool.java文件,第二次就不用再编译工具类啦。

        如果把这个.java文件删掉,编译就会出错。

        下一个问题:我们有必要建立这个对象吗?

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第19张图片

        不用仔细想,就知道,这个对象,并没有用到ArrayTool类中的特有属性和特有功能。

        总结一下:

        虽然可以通过建立ArrayTool的对象使用这些工具方法,对数组进行操作。

        但发现了问题:

        1,对象是用于封装数据的,可是ArrayTool对象并未封装特有数据。

        2,操作数组的每一个方法都没有用到ArrayTool对象中的特有数据。

        这时就考虑,让程序更严谨,是不需要对象的。

        可以将ArrayTool中的方法都定义成static的。直接通过类名调用即可。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第20张图片
定义静态

        直接这样调用就OK啦:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第21张图片

        将方法都静态后,可以方便于使用,但是该类还是可以被其他程序建立对象的。

        为了更为严谨,强制让该类不能建立对象。

        可以通过将构造函数私有化来完成。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第22张图片
构造函数私有化

        到这里,这个工具类的功能基本完善啦。

        还有一个细节上的小问题:交换的这个功能是工具类中其他方法需要调用到的,并不对外提供使用,也将它私有化~

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第23张图片

        总之,能隐藏起来的就隐藏起来,不需要暴露别人不需要知道的东西。

    05-面向对象(帮助文档的制作javadoc)


        接下来,将ArrayTool.class文件发给其他人,其他人只要将该文件设置到classpath路径下,就可以使用该工具类。

        但是,很遗憾,该类中到底定义了多少个方法,使用者并不清楚。因为该类中并没有说明书。

        工具类做好了,使用者不会使用怎么办呢?这个时候就需要制作说明书。

        开始制作程序的说明书。java的说明书通过文档注释来完成。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第24张图片
对整个类的说明
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第25张图片
对方法的说明
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第26张图片
对方法的说明
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第27张图片
对方法的说明
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第28张图片
对方法的说明

        现在文档注释已经写完了,我们需要用另外的工具对文档注释进行提取和输出。

        这个工具叫javadoc。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第29张图片

        如果想把一个类生成帮助文档,这个类必须是公共类,要加上public修饰符。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第30张图片

        这样就成功啦:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第31张图片

        生成了好多文件,我们看哪一个呢?一个一个去看吗?哈哈哈。当然是看这个啦:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第32张图片

        打开后是酱紫:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第33张图片
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第34张图片

        注意私有的方法是不会出现在这个文档中的哦。只有两种权限的方法才会被提取到这个文档中,一个叫public,一个叫protect。

        点击方法进去是这样的,注意不会显示具体的实现细节哦,直接拿去用就可以了,使用者不用了解它怎么实现的。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第35张图片

        注意这里面试没有构造函数的哦,因为构造函数是私有的:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第36张图片

        我们修改一下,不私有但是也不加公有,发现说明文档里依然不会显示。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第37张图片
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第38张图片

        加上public修饰符:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第39张图片

        有啦:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第40张图片

        一个类中默认会有一个空参数的构造函数。

        这个默认的构造函数的权限和所属类一致。

        如果类被public修饰,那么默认的构造函数也带public修饰符。

        如果类没有被public修饰,那么默认的构造函数,也没有public修饰。

        默认构造函数的权限是随着类的变化而变化的。

        当然,不要以为如下的构造函数就是默认构造函数:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第41张图片

        这是一个空参数构造函数,而不是默认构造函数,这样写叫自定义构造函数。不写的话,构造函数就是默认的。默认是看不见的:

        刚刚做的那个文档,叫程序的说明文档或者帮助文档,也叫做API文档。

        API是什么呢?

        API的全称是:Appliacation Program Interface(应用程序接口)。

        Java为了让用户方便使用,也做了一个帮助文档。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第42张图片

        所不同的是,我们刚刚做的只有一个类,而这个帮助文档有好多类。而且这些类还被分别存储到不同的包中。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第43张图片

        比如说java.lang这个包:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第44张图片

        比如Array这个类中的方法:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第45张图片

        有了帮助文档真方便!

        我们写好了帮助文档,需要把类(.class文件)和帮助文档一并发过去,让用户使用~

    06-面向对象(静态代码块)

        接下来说一个小知识点,静态代码块。

        静态代码块格式:        

        static

        {

                静态代码块中的执行语句。

        }

        比如:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第46张图片

        可是它也没有名字,没人调用怎么执行呢?

        注意,静态代码块的特点:

        随着类的加载而执行,只执行一次,并优先于主函数。

        用于给类进行初始化。

        当然这个相对少用一点,一般都是给对象初始化比较多。

        这样一段程序:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第47张图片

        它的执行结果是怎样呢?

        我们来分析一下:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第48张图片

        因此运行结果的打印顺序为:

        b c a over

        是不是类必须要有对象才能加载静态代码块呢?

        不是的。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第49张图片

        定义一个静态方法show(),采用类名调用,想要调用这个方法,就必须加载StaticCode类,因此静态代码块就会被加载。

        但这种情况下静态代码块不会被加载,因为类没有存在的意义:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第50张图片

        加上以下任意一句,静态代码块就被加载了,因为用到了类中的函数。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第51张图片

        可能会有疑惑,第一句用到了类中的什么呢?用到了类里面的默认构造函数呀。

        增加一丢丢难度,StaticCode类中这样写:        

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第52张图片

        StaticDemo类中这样写:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第53张图片

        运行结果会怎样呢?        

        运行结果是:a c d

        分析一下:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第54张图片

        再一个问题:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第55张图片

        报错啦。

        因为静态代码块,只能访问静态变量。

        但在构造代码块中就阔以:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第56张图片

    07-面向对象(对象的初始化过程)

        Person p=new Person("zhangsan",20);        

        这句话都做了什么事情?

        1,因为new用到了Person.class,所以会先找到Person.class文件并加载到内存中。

        2,执行该类中的static代码块,如果有的话,给Person.class类进行初始化。

        3,在堆内存中开辟空间,分配内存地址。

        4,在对内存中建立对象的特有属性,并进行默认初始化。

        5,对属性进行显式初始化。

        6,对对象进行构造代码块初始化。

        7,对对象进行对应的构造函数初始化。

        8,将内存地址赋给栈内存中的p变量。

    08-面向对象(对象调用成员过程)

        图有点小乱,栈内存中大概就是如下的过程:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第57张图片
1
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第58张图片
2
Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第59张图片

        这样才对哦:

    09-面向对象(单例设计模式)

        设计模式:解决某一类问题最行之有效的方法。

        java中23中涉及模式:

        单例设计模式:解决一个类在内存只存在一个对象。

        想要保证对象唯一的原因:

        1,为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象。

        2,还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。

        3,为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。

        这三步具体怎么用代码体现呢?

        1,将构造函数私有化。

        2,在类中创建一个本类对象。

        3,提供一个方法可以获取到该对象。

        整体是这样的:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第60张图片

        但是有个问题,没有对象就没有办法调用这个方法,所以需要将这个方法用static修饰。而静态方法只能访问静态成员,因此s也需要被static修饰,同时s只是在类内部被调用,所以将它私有化。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第61张图片

        内存中是这样的:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第62张图片

        不管new多少个对象,都指向同一个对象,内存中只存在一个,保证了对象的唯一性。

        运行下面这段程序:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第63张图片

        运行结果:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第64张图片

        将Single(){}私有化:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第65张图片

        运行结果:

        对于事物该怎么描述,还怎么描述。

        当需要将该事物的对象保证在内存中唯一时,就将以上的三步加上即可。

    10-面向对象(单例设计模式方式二)

        两种初始化方式:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第66张图片

        饿汉式:

        先初始化对象。

        Single类一进内存,就已经创建好了对象。

        懒汉式:

        对象是方法被调用时,才初始化。也叫做对象的延时加载。

        Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象。

        其实先创建后创建也都差不多,区别不大。懒汉式一般实际开发中不常用,什么时候用呢?面试的时候用,哈哈。注意开发一般用饿汉式,因为它安全,而且简单。

        而懒汉式存在一个问题,如果一个人调用这个方法,没有问题。如果多个人同时调用这个方法,就会发生问题。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第67张图片

        A、B先后进来,A new了一个对象,return了,B也跟着new了一个对象,这个时候对象就不唯一了。

        也有解决方法,加一个锁,这样A进去之后,其他就进不去了。

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第68张图片

        但是用了这个锁,运行效率就降低了,每次要用这个功能,都得先判断一下里面有人没。

        有没有既不低效又有用的方法呢?

        我们可以用双重判断的方法来完成,最终解决方案:

Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式_第69张图片

        它相对不低效的原因是减少了用锁的次数,刚开始第一个第二个会判断时候可以开锁,后面的在第一个if(s==null)这里就被拦住了,直接return s。

        这个方法虽然不低效了,但是代码量大了。

        所以还是饿汉式方法更好用一些。而且饿汉式不会出问题的,因为它里面就一句话,return s。

        记住原则:定义单例,建议用饿汉式。

        2018-12-3

        之前结尾还有一丢丢没有写详细,今天整理完day07的笔记后又将这边结尾处重新补充完整了,这下没遗憾了,嘻嘻。

        补这个后记凑一下字数,本篇也5000+啦。

你可能感兴趣的:(Java基础day06笔记:Static关键字|main函数|静态|帮助文档|对象的初始化过程|单例设计模式)