Java基础之静态修饰符知识点总结
2017-12-07 11:45
661 查看
静态修饰的特点: static是一个修饰符,用于修饰成员(成员变量和成员函数)。 1,静态成员随着类的加载而加载。 2,静态成员优先于对象存在。 3,静态成员被所有对象所共享 4,静态成员中多了一个调用方式,可以被类名直接调用。 静态使用的注意事项。 1,静态方法只能访问静态成员。 非静态方法既可以访问静态又可以访问非静态。 2,静态方法中不可以定义this,super关键字。 因为this代表是对象。而静态存在时,有可能没有对象。所以静态方法运行时,this是没有任何对象代表的。 简单说,先进内存的数据不可以访问后进内存的数据,可是后进内存数据可以访问先进内存的数据。 3,主函数是静态的。 静态: 好处:静态成员多了一种调用方式。可以直接被类名调用 格式 :类名.静态成员。也可以被对象调用。 弊端:静态方法只能访问静态成员,出现了访问局限性。 静态修饰的数据对象共享的数据,存放在方法区的静态区中。 非静态的数据,是每一个对象特有数据。存放在对象的所属的堆内存中。
例子1:静态修饰符static的用法实例。[java] view plain copy 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:静态成员的调用方式。
[java] view plain copy 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:定义静态成员函数的实例演示。
[java] view plain copy 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:静态函数的实例演示。
[java] view plain copy 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:主函数分析的实例演示。
[java] view
plain copy
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:静态代码块的实例演示。
[java] view plain copy package cn.itheima.day18; //运行顺序:静态代码块---> 1f14e ;构造代码块--->构造函数 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:单例模式的实例演示。
[java] view plain copy 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:单例设计模式(懒汉式)的实例演示。
[java] view plain copy 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); } }
使用时,一般使用饿汉式。 而面试时,都面试懒汉式,因为涉及的技术细节很多。 面向常见问法:请写出一个单例延迟加载的示例。这个考的就是懒汉式.
相关文章推荐
- Java基础之静态修饰符知识点总结
- 黑马程序员:Java基础总结----(小知识点)foreach循环
- java基础知识点总结
- JAVA基础知识点总结
- Java基础知识点总结三
- 黑马程序员:Java基础总结----静态代理模式&动态代理
- JAVA基础知识点(自己总结的)
- Java基础知识点总结七
- Java基础知识点总结一
- Java基础知识点总结二
- Java基础之IO流知识点总结二
- Java基础之网络编程知识点总结
- java基础总结知识点
- java基础编程学习过程中的知识点 -- 个人总结
- Java基础知识点总结四
- java基础重要知识点总结
- 黑马程序员:Java基础总结----静态代理模式&动态代理
- Java 面向对象(基础) 知识点总结I
- Java基础知识点总结五
- Java 面向对象(基础) 知识点总结I