Java基础之静态修饰符知识点总结

来源:互联网 发布:一知f君张碧晨 编辑:程序博客网 时间:2024/06/10 19:47


静态修饰的特点static是一个修饰符,用于修饰成员(成员变量和成员函数)。   1,静态成员随着类的加载而加载。   2,静态成员优先于对象存在。   3,静态成员被所有对象所共享   4,静态成员中多了一个调用方式,可以被类名直接调用。静态使用的注意事项   1,静态方法只能访问静态成员。       非静态方法既可以访问静态又可以访问非静态。   2,静态方法中不可以定义this,super关键字。       因为this代表是对象。而静态存在时,有可能没有对象。所以静态方法运行时,this是没有任何对象代表的。       简单说,先进内存的数据不可以访问后进内存的数据,可是后进内存数据可以访问先进内存的数据。   3,主函数是静态的。静态:    好处:静态成员多了一种调用方式。可以直接被类名调用     格式 :类名.静态成员。也可以被对象调用。    弊端:静态方法只能访问静态成员,出现了访问局限性。    静态修饰的数据对象共享的数据,存放在方法区的静态区中。    非静态的数据,是每一个对象特有数据。存放在对象的所属的堆内存中。
例子1:静态修饰符static的用法实例。
package cn.itheima.day18;class Person{String name; static String country = "CN";public static void show(){System.out.println("country="+country);}}public class StaticDemo {public static void main(String[] args) {         //静态成员多了一种调用方式。直接可以被类名所调用。Person.show();Person p = new Person();p.name="zhangsan";System.out.println(p.name);Person p2 = new Person();p2.name="lisi";System.out.println(p2.name);}}
当成员变量被静态修饰后。静态成员变量和非静态成员变量的区别:  1,静态变量也称为类变量,也就是直接可以被类名调用的变量。这个变量是所属于类的。       非静态变量成为成员变量,或者实例变量,是被对象调用的,是所属具体对象的。  2,静态变量随着类的加载而加载,也意味着随着类的消失而消失。生命周期最长。       实例变量,随着对象的创建而加载,随着对象的消失而消失。按照对象的生命周期而存在。  3,静态变量存储在方法区的静态区中。       实例变量存在于对象所属的堆内存中。   4,静态变量数据,被所有对象所共享。       实例变量是对象中的特有数据。任何成员被访问使用,必须要被调用。如果是非静态成员,必须要被对象调用。在本类中调用是使用的是this。如果是静态成员,必须要被类名调用。只不过在书写时,可以省略。静态变量在静态区中也会进行默认初始化。
例子2:静态成员的调用方式。
package cn.itheima.day18;class Demo{int num1 = 3;static int num2 = 5;void show(){System.out.println("num1="+this.num1);System.out.println("num2="+Demo.num2);}static void method(){System.out.println("num2="+Demo.num2);}}public class StaticDemo2 {public static void main(String[] args) {Demo d = new Demo();d.show();d.method();System.out.println("------------");Demo.method();}}
什么时候使用static呢?成员变量:    什么时候被静态修饰呢?    当该成员变量所存储的数据,每一个对象都是一样的,这时没有必要把该数据存储到每一个对象中,只要让所有对象共享该数据即可,这时成员就需要被static修饰。当数据需要被对象共享时,就使用static修饰。这样可以对共享的数据节约内存。成员函数:    当成员函数内并没有访问对象中的特有数据时,就将该方法定义成静态的。    简单说:该函数如果访问了成员变量,该函数就是非静态的。该函数没有访问过成员变量,或者访问过静态的成员变量,那么为了程序的严谨性,将该方法定义成静态的。因为该方法不需要对象存在,既可以使用。
例子3:定义静态成员函数的实例演示。
package cn.itheima.day18;class Person1{String name;static String country = "CN";Person1(String name){this.name = name;}public void show(){System.out.println("name="+this.name);}public static void method(){System.out.println("country="+Person1.country);}}public class StaticDemo3 {public static void main(String[] args) {Person1 p1 = new Person1("aa");p1.show();Person1 p2= new Person1("bb");p2.show();Person1.method();}}
例子4:静态函数的实例演示。
package cn.itheima.day18;/*其中的每一个功能都没有对该类的对象的特有数据进行访问,那么这些功能,就不需要对象调用。除了对象调用方式外,还有一个类名调用方式。所以可以将这些功能都定义成static的。        这个类中的功能都被静态化后,只要使用类名调用即可。但是其他程序在使用该类时,因为该类中有一个默认的构造函数,所以其他程序还可以建立该类对象,而该类并不需要对象就可以使用类中的成员。所以这个对象建立是没有意义的。为了提高程序的严谨性。应该强制不让其他程序建立该类对象。当该类中的属性或者行为都是静态的时候,该类创建对象是非常没有意义的。所以就要强制不让其他程序建立对象,也就是将该类的构造函数私有化。这样,你即使建立了该类对象,也没有办法初始化。 */public class ArrayTool {    private ArrayTool(){}  //不让其他的程序创建该类文件    //对int类型的数组进行排序。从小到大。    public static void sort(int[] arr){    for(int x = 0;x<arr.length-1;x++){    for(int y = x+1;y<arr.length;y++){    if(arr[x]>arr[y]){    swap(arr,x,y);    }    }    }    }       //给数组进行换位操作。private static void swap(int[] arr, int x, int y) {int temp = arr[x];arr[x] = arr[y];arr[y]=temp;}//将int数组转换成字符串。public static String arrToString(int[] arr){String str="[";for(int x = 0;x<arr.length;x++){if(x!=arr.length-1){str=str+arr[x]+",";}else {str = str+arr[x]+"]";}}return str;}//获取数组中的最大值。public static int getMax(int[] arr){int max=0;for(int x = 1;x<arr.length;x++){if(arr[x]>arr[max]){max =x;}}return arr[max];}}---------------------------------package cn.itheima.day18;public class ArrayToolDemo {public static void main(String[] args) {int[] arr = {3,1,4,5};String str1 = ArrayTool.arrToString(arr);System.out.println(str1);ArrayTool.sort(arr);String str = ArrayTool.arrToString(arr);System.out.println(str);}}
主函数静态的,说明主函数只能直接访问静态的成员。   public static void main(String[] args)    public: jvm调用的函数必须权限足够大。所以被public修饰。   static: 主函数随着类的加载而加载,jvm不需要创建该类对象既可以完成对该函数的调用,所以是静态的。   void: 主函数没有返回值。   main: 函数名,是固定的,jvm认识。   (String[]args):主函数的参数列表,参数类型是:一个字符串数组类型的参数。   args:参数名称。  主函数有参数,那么jvm调用的时候,就需要传入相对应的实际参数。问:jvm调用主函数时,到底传入了什么呢?//System.out.println(args);//[Ljava.lang.String;@de6ced//[Ljava.lang.String;@de6ced:通过这个结果看到,args指向了一个具体的数组实体。//而且该数组中的元素是String类型的。        System.out.println(args.length);//0//通过两个输出语句,就可以验证,jvm给主函数传递的实际参数是: new String[0];这是jvm传入的默认值。但是没什么用,所以我们在使用main时,可以自定义该主函数数组中的元素。
例子5:主函数分析的实例演示。
package cn.itheima.day18;public class MainDemo {    int x = 4;public static void main(String[] args) {//System.out.println(args);//[Ljava.lang.String;@de6ced//[Ljava.lang.String;@de6ced:通过这个结果看到,args指向了一个具体的数组实体。//而且该数组中的元素是String类型的。System.out.println(args.length);//0//通过两个输出语句,就可以验证,jvm给主函数传递的实际参数是: new String[0];/*这是jvm传入的默认值。但是没什么用,所以我们在使用main时,可以自定义该主函数数组中的元素。*/     String arr[]={"haha","hehe","heihei","xixi"};     new MainDemo().show();         Test.main(arr);}public void show(){System.out.println("x="+x);}}class Test{public static void main(String[] args){for(int a=0;a<args.length;a++){System.out.println(args[a]);}}}
静态代码块。格式:static{    code..;}     作用:当类在加载进内存时,如果需要进行一些内容的执行,完成一个类的初始化。就需要使用静态代码块来完成,给类进行初始化。   执行特点:当类被加载时,静态代码就执行了,而且只执行一次。而且优先于main函数执行。
例子6:静态代码块的实例演示。
package cn.itheima.day18;//运行顺序:静态代码块--->构造代码块--->构造函数class StaticCode{{   //静态代码块System.out.println("AAAAA");}static{   //静态代码块System.out.println("a");}public StaticCode() {System.out.println("StaticCode");}static void show(){System.out.println("show run");}}public class StaticCodeDemo {    static {    System.out.println("b");    }public static void main(String[] args) {System.out.println("d");//StaticCode.show();new StaticCode();System.out.println("e");}static{System.out.println("c");}}//打印结果:/*  * b  c  d  a  AAAAA  StaticCode  e */
设计模式:就是解决某类问题最行之有效的解决方案,设计模式是一种思想。java中总结出来23种设计模式。单例设计模式(23种设计模式之一):    解决的问题:保证一个类在内存中的只存在一个对象。    简单说:保证一类在内存中的对象唯一性。    应用场景:比如配置文件。A要使用配置文件对象。B程序也要使用配置文件对象。希望A程序对配置数据修改后,B程序可以直接使用,那么就需要A程序,和B程序使用的同一个对象.如何保证一个类在内存中的对象唯一性呢?    1)为了控制该类的对象建立,不让其他程序建立该类的对象。    2)在本类中自定义一个本类对象。    3)对外提供获取该对象的方式即可。代码如何实现呢?    1)可以将构造函数私有化。这样对方程序创建就无法初始化。已达到不允许,其他程序创建对象的目的。    2)在本类中,通过new创建一个本类对象。    3)提供一个公共的方法返回该对象,方便于其他程序获取该对象。代码体现具体:    1)私有化构造函数。    2)创建一个私有并静态的本类的对象。    3)创建一个公共的static方法返回该对象。
例子7:单例模式的实例演示。
package cn.itheima.day18;//饿汉式class Single{private static Single s = new Single();private Single(){}public static Single getInstance(){return s;}}//需要保证Demo类在内存中的对象唯一性。只要保证一个类的对象唯一性class Demo3{private int num = 4;private static Demo3 d = new Demo3();//类一加载,该对象就已经存在了。private Demo3(){}public static Demo3 getInstance(){return d;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}}public class SingleDemo {public static void main(String[] args) {/*Single ss = Single.getInstance();Single ss1 = Single.getInstance();System.out.println(ss==ss1);*/Demo3 d1 = Demo3.getInstance();Demo3 d2 = Demo3.getInstance();d1.setNum(10);d2.setNum(20);System.out.println("d1.num="+d1.getNum());System.out.println("d2.num="+d2.getNum());}}
对象的延迟加载方式。这种方式看上去很美,但是当并发访问getInstance方法时,容易出现安全隐患(线程安全问题)懒汉式
例子8:单例设计模式(懒汉式)的实例演示。
package cn.itheima.day18;//饿汉式class Single1{private static Single1 s = null;private Single1(){}public static Single1 getInstance(){if(s==null){s =  new Single1();}return s;}}public class SingleDemo1 {public static void main(String[] args) {Single1 ss = Single1.getInstance();Single1 ss1 = Single1.getInstance();System.out.println(ss==ss1);}}
使用时,一般使用饿汉式。而面试时,都面试懒汉式,因为涉及的技术细节很多。面向常见问法:请写出一个单例延迟加载的示例。这个考的就是懒汉式.

0 0
原创粉丝点击