黑马程序员——Java基础:static关键字、单例设计模式
2015-06-18 16:48
573 查看
——- android培训、java培训、期待与您交流!
———-
一、static静态关键字
用法:是一个修饰符,用于修饰成员(成员变量,成员函数)
当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用:类名.静态成员
特点:1.随着类的加载而加载,随着类的消失而消失,说明它的生命周期最长。
2.优先于对象存在,静态是先存在的,对象是后存在的。
3.被所有对象共享(数据是对象共有的)
4.可以直接被类名所调用。
实例变量和类变量的区别?
1.别名不同
成员变量又称实例变量
静态变量又称类变量
2.存放位置不同
类变量随着类的加载而存在于方法区(共享数据区)的静态区中,所以也叫对象的共享数据。
实例变量随着对象的建立而存在于堆内存中,也叫做对象的特有数据。
3.调用方式不同
类变量可以被对象调用,还可以被类名调用
实例变量只能被对象调用
4.生命周期不同(类变量>对象>实例变量)
类变量生命周期最长,随着类的加载而存在,随着类的消失而消失。
实例变量生命周期,随着对象的创建而存在,随着对象的回收而释放。
静态使用的注意事项:
1.静态方法只能访问静态成员(方法和变量),非静态方法既可以访问静态,也可以访问非静态。
2.静态方法中不可以定义this,super关键字,因为静态优先于对象存在,所以静态方法中不可以出现this。
3.主函数是静态的。
静态的好处:对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象都存储一份,可以直接被类调用。
静态的弊端:生命周期过长,访问出现了局限性(静态虽好,但只能访问静态)。
示例:
注:public static void main(String[] args)是一个特殊的函数,作为程序的入口,可以被JVM(java虚拟机)调用。
public:代表着该函数的访问权限最大
static:代表主函数随着类的加载就已近存在了
void:主函数没有具体的返回值
main:不是关键字,但是是一个特殊的单词,可以被JVM识别
(String[] args):函数的参数,参数类型是一个数组,该数组中的元素是字符串,是字符串类型的数组
主函数是固定格式的,被JVM识别。
JVM在调用主函数时,传入的是new String[0];
示例:
运行结果为:
注:java 类名 参数,将值传入。就相当于String[ ] args="haha,kaka";
什么时候使用静态?
从修饰静态成员变量和函数入手。
1).什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰。
当对象中有特有数据要定义成非静态存在于堆内存中。
2).什么时候定义静态函数呢?
当功能内部没有访问到非静态数据(对象的特有数据)时,该功能可以定义成静态的。
简单点说,从源代码看,该功能是否需要访问非静态的成员变量,如果需要,该功能就是非静态的。
如果不需要,就可以将该功能定义成静态的。当然,也可以定义成非静态,但是非静态需要被对象调用。
如果没有访问特有数据的方法,该对象的创建是没有意义。
静态的应用:
每一个应用程序中都有共性的功能,可以将这些功能进行抽取,独立封装成类,以便复用。
示例:定义一个类ArrayTool,在该类中可以对整数数组进行查询其中最大值,最小值,排序,打印等功能。
在另一个文件中调用该类,使用其中方法:
运行结果为:
如果将ArrayTool77.class文件发送给其他人,其他人只要将该文件设置到classpath路径下,即可使用该工具类。但是,该类中到底定义了多少个方法,对方却不清楚,因为该类并没有使用说明书。
那么如何[b]制作说明书呢?Java的说明书是通过文档注释(/** 注释内容 */)来完成的。可以将ArrayTool77类制作成说明书。方法如下:
注:这里的ArrayTool77类必须是public或者protected权限的。
如果出现如上的情况,说明生成成功,会生成MyHelp文件夹,文件夹中的内容如下:
打开index,既是打开ArrayTool77类的说明书:
静态代码块:
格式:static { 静态代码块中的执行语句 }
特点:随着类的加载而执行,只执行一次,并且优先于主函数。
作用:给类进行初始化,用到类中的内容就加载了。
示例1:
运行结果为:
注:由代码显示可得知:静态代码块可以定义多次,且每一个只执行一次,且优先于主函数。
示例2:
运行结果为:
注:这里的num不可以放在静态代码块中,因为无法从静态上下文中引用非静态变量
二、单例设计模式
设计模式:解决某一类问题最行之有效的方式。
单例设计模式:解决一个类在内存中只存在一个对象的问题,保证对象的唯一性。例如:A、B两个人只对同一个文件进行操作。
如何保证对象唯一性?
1.为了避免其他程序过多的建立该类对象,先禁止其他程序建立该类对象
2.为了其他程序可访问到该类对象,只好在本类中自定义一个对象
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式
这三步的代码体现:
1.将构造函数私有化
2.在本类中创建一个本类对象
3.提供一个方法可以获取该类对象
示例(饿汉式):先初始化对象。
运行结果为:true
注:Single1类一进内存,就创建好了对象。之所以不用Single.s;的方式获取Single对象,而采用getInstance获取是因为在getInstance方法中我们可以做一些判断来决定是否返回Single的对象,也就是实现了对单例对象的可控。所以,给Single的构造方法加上了private限制,禁止使用者直接采用Single.s;的方式获取。
示例(懒汉式):对象方法被调用时才初始化,也叫做对象的延时加载。
运行结果为:true
注:Single2类进入内存,对象还没有建立,只有调用了getSingle2方法时,才建立了对象。当多线程访问时,会出现安全问题,可以加同步代码块或同步函数方式实现。但比较低效,可使用双重判断的形式来解决效率问题。加同步的时候,使用的锁是该类所属的字节码文件对象。
示例:
运行结果为:
——- android培训、java培训、期待与您交流!
———-
———-
一、static静态关键字
用法:是一个修饰符,用于修饰成员(成员变量,成员函数)
当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用:类名.静态成员
特点:1.随着类的加载而加载,随着类的消失而消失,说明它的生命周期最长。
2.优先于对象存在,静态是先存在的,对象是后存在的。
3.被所有对象共享(数据是对象共有的)
4.可以直接被类名所调用。
实例变量和类变量的区别?
1.别名不同
成员变量又称实例变量
静态变量又称类变量
2.存放位置不同
类变量随着类的加载而存在于方法区(共享数据区)的静态区中,所以也叫对象的共享数据。
实例变量随着对象的建立而存在于堆内存中,也叫做对象的特有数据。
3.调用方式不同
类变量可以被对象调用,还可以被类名调用
实例变量只能被对象调用
4.生命周期不同(类变量>对象>实例变量)
类变量生命周期最长,随着类的加载而存在,随着类的消失而消失。
实例变量生命周期,随着对象的创建而存在,随着对象的回收而释放。
静态使用的注意事项:
1.静态方法只能访问静态成员(方法和变量),非静态方法既可以访问静态,也可以访问非静态。
2.静态方法中不可以定义this,super关键字,因为静态优先于对象存在,所以静态方法中不可以出现this。
3.主函数是静态的。
静态的好处:对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象都存储一份,可以直接被类调用。
静态的弊端:生命周期过长,访问出现了局限性(静态虽好,但只能访问静态)。
示例:
class Person{ private String name;//成员变量/实例变量 static String country="CN";//静态的成员变量/类变量 public static void show(){ System.out.println("country2="+country); } } public class Test4 { public static void main(String[] args) { //类名调用 System.out.println("country="+Person.country); Person.show(); } }运行结果为:
注:public static void main(String[] args)是一个特殊的函数,作为程序的入口,可以被JVM(java虚拟机)调用。
public:代表着该函数的访问权限最大
static:代表主函数随着类的加载就已近存在了
void:主函数没有具体的返回值
main:不是关键字,但是是一个特殊的单词,可以被JVM识别
(String[] args):函数的参数,参数类型是一个数组,该数组中的元素是字符串,是字符串类型的数组
主函数是固定格式的,被JVM识别。
JVM在调用主函数时,传入的是new String[0];
示例:
class Test6 { public static void main(String[] args) { for(int i=0;i<args.length;i++) { System.out.println(args[i]); } } } <span style="font-size:14px;"> </span>
运行结果为:
注:java 类名 参数,将值传入。就相当于String[ ] args="haha,kaka";
什么时候使用静态?
从修饰静态成员变量和函数入手。
1).什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰。
当对象中有特有数据要定义成非静态存在于堆内存中。
2).什么时候定义静态函数呢?
当功能内部没有访问到非静态数据(对象的特有数据)时,该功能可以定义成静态的。
简单点说,从源代码看,该功能是否需要访问非静态的成员变量,如果需要,该功能就是非静态的。
如果不需要,就可以将该功能定义成静态的。当然,也可以定义成非静态,但是非静态需要被对象调用。
如果没有访问特有数据的方法,该对象的创建是没有意义。
静态的应用:
每一个应用程序中都有共性的功能,可以将这些功能进行抽取,独立封装成类,以便复用。
示例:定义一个类ArrayTool,在该类中可以对整数数组进行查询其中最大值,最小值,排序,打印等功能。
/*java的说明书通过文档注释来完成*/ /** 这是一个数组操作类,在该类中可以对整型数组进行 查询其中最大值,最小值,排序,打印等功能。 @author huan @version v1.0 */ public class ArrayTool77//只有public protected才可以创建文档 { private ArrayTool77(){}//强制让该类不能创建对象,外界想使用该对象只能类名调用 /** 获取数组中的最大值 @param arr 接收一个整型类型的数组 @return max 返回数组中的最大值 */ public static int getMax(int[] arr) { int max=arr[0]; for(int i=0;i<arr.length;i++) { if(max<arr[i]) max=arr[i]; } return max; } /** 获取数组中的最小值 @param arr 接收一个整型类型的数组 @return min 返回数组中的最小值 */ public static int getMin(int[] arr) { int min=arr[0]; for(int i=0;i<arr.length;i++) { if(min>arr[i]) min=arr[i]; } return min; } /** 将数组从小到大进行选择排序 @param arr 接收一个整型类型的数组 */ public static void xuZeSort(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); /* int temp; temp=arr[x]; arr[x]=arr[y]; arr[y]=temp;*/ } } } } /** 将数组从小到大进行冒泡排序 @param arr 接收一个整型类型的数组 */ public static void maoPaoSort(int[] arr) { for(int x=0;x<arr.length-1;x++) { for(int y=0;y<arr.length-x-1;y++) { if(arr[y]>arr[y+1]) { swap(arr,y,y+1); /* int temp; temp=arr[y]; arr[y]=arr[y+1]; arr[y+1]=temp; */ } } } } /** 给数组中的元素进行位置置换 @param arr 接收一个整型类型的数组 @param a 要置换的位置 @param b 要置换的位置 */ private static void swap(int[] arr,int a,int b) { int temp; temp=arr[a]; arr[a]=arr; arr[b]=temp; } /** 打印数组中的元素 @param arr 接收一个整型类型的数组 */ public static void print(int[] arr) { System.out.print("{"); for(int i=0;i<arr.length;i++) { if(i!=arr.length-1) System.out.print(arr[i]+","); else System.out.println(arr[i]+"}"); } } } <span style="font-size:12px;"> </span>
在另一个文件中调用该类,使用其中方法:
class StaticDemo77 { public static void main(String[] args) { int[] arr=new int[]{3,1,5,7,4,8}; int max=ArrayTool77.getMax(arr); System.out.println("max="+max); int min=ArrayTool77.getMin(arr); System.out.println("min="+min); ArrayTool77.xuZeSort(arr); ArrayTool77.print(arr); ArrayTool77.maoPaoSort(arr); ArrayTool77.print(arr); } } <span style="font-size:12px;"> </span>
运行结果为:
如果将ArrayTool77.class文件发送给其他人,其他人只要将该文件设置到classpath路径下,即可使用该工具类。但是,该类中到底定义了多少个方法,对方却不清楚,因为该类并没有使用说明书。
那么如何[b]制作说明书呢?Java的说明书是通过文档注释(/** 注释内容 */)来完成的。可以将ArrayTool77类制作成说明书。方法如下:
注:这里的ArrayTool77类必须是public或者protected权限的。
如果出现如上的情况,说明生成成功,会生成MyHelp文件夹,文件夹中的内容如下:
打开index,既是打开ArrayTool77类的说明书:
静态代码块:
格式:static { 静态代码块中的执行语句 }
特点:随着类的加载而执行,只执行一次,并且优先于主函数。
作用:给类进行初始化,用到类中的内容就加载了。
示例1:
class StaticCode { static//静态代码块 { System.out.println("A"); } } class StaticDemo { static { System.out.println("B"); } public static void main(String[] args) { new StaticCode(); new StaticCode(); System.out.println("C"); } static { System.out.println("D"); } }
运行结果为:
注:由代码显示可得知:静态代码块可以定义多次,且每一个只执行一次,且优先于主函数。
示例2:
class StaticCode { int num=9; StaticCode()//构造函数 { System.out.println("B"); } static//静态代码块 { System.out.println("A"); } {//构造代码块 System.out.println("C"+this.num); } StaticCode(int x) { System.out.println("D"); } } class StaticDemo { static { System.out.println("F"); } public static void main(String[] args) { new StaticCode(); System.out.println("==============="); new StaticCode(4); } }
运行结果为:
注:这里的num不可以放在静态代码块中,因为无法从静态上下文中引用非静态变量
二、单例设计模式
设计模式:解决某一类问题最行之有效的方式。
单例设计模式:解决一个类在内存中只存在一个对象的问题,保证对象的唯一性。例如:A、B两个人只对同一个文件进行操作。
如何保证对象唯一性?
1.为了避免其他程序过多的建立该类对象,先禁止其他程序建立该类对象
2.为了其他程序可访问到该类对象,只好在本类中自定义一个对象
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式
这三步的代码体现:
1.将构造函数私有化
2.在本类中创建一个本类对象
3.提供一个方法可以获取该类对象
示例(饿汉式):先初始化对象。
class Single1 { //private:不能够创建对象,只能类名调用,所以getInstance()要是静态的 //因为静态只能访问静态,所以s也要是静态的,因为s是该类中的特有数据,所以是private private Single1(){} private static Single1 s=new Single1(); public static Single1 getSingle1() { return s; } } class SingleDemo { public static void main(String[] args) { Single1 s1=Single1.getSingle1(); Single1 s2=Single1.getSingle1(); System.out.println(s1==s2); } }
运行结果为:true
注:Single1类一进内存,就创建好了对象。之所以不用Single.s;的方式获取Single对象,而采用getInstance获取是因为在getInstance方法中我们可以做一些判断来决定是否返回Single的对象,也就是实现了对单例对象的可控。所以,给Single的构造方法加上了private限制,禁止使用者直接采用Single.s;的方式获取。
示例(懒汉式):对象方法被调用时才初始化,也叫做对象的延时加载。
class Single2 { private Single2(){} private static Single2 s=null; public static Single2 getSingle2() { if(s==null) s=new Single2(); return s; } } class SingleDemo { public static void main(String[] args) { Single2 s1=Single2.getSingle2(); Single2 s2=Single2.getSingle2(); System.out.println(s1==s2); } }
运行结果为:true
注:Single2类进入内存,对象还没有建立,只有调用了getSingle2方法时,才建立了对象。当多线程访问时,会出现安全问题,可以加同步代码块或同步函数方式实现。但比较低效,可使用双重判断的形式来解决效率问题。加同步的时候,使用的锁是该类所属的字节码文件对象。
示例:
class Single2 { private Single2(){} private static Single2 s=null; public static Single2 getSingle2() { if(s==null) { synchronized(Single2.class) { if(s==null) s=new Single2(); } } return s; } } class SingleDemo { public static void main(String[] args) { Single2 s1=Single2.getSingle2(); Single2 s2=Single2.getSingle2(); System.out.println(s1==s2); } }
运行结果为:
——- android培训、java培训、期待与您交流!
———-
相关文章推荐
- "一个程序员的生命周期"读后感
- 《C程序员:从校园到职场》出版预告(1):从“高大上”到“柴米油盐”
- 【程序员面试宝典】找规律
- 杂乱的面试题---
- 终于体会到数学对于程序员的魅力
- 构建之法-软件测试+质量保障+稳定和发布阶段+IT行业的创新+人、绩效和职业道德
- 黑马程序员学习日记--反射
- 让程序员跳槽的非钱原因
- 阅读<构建之法>第13、14、15、16、17章 与 《一个程序员的生命周期》读后感
- 我曾经面试过这样一个问题
- 黑马程序员——Java基础——IO输入与输出_3
- 关于职业发展
- 百度面试相关问题
- 15款java程序员必备的开发工具
- 阅读《构建之法》第13-17章和读《一个程序员的生命周期》有感
- 黑马程序员---String类
- 安卓面试题
- java程序员进阶过程
- Java程序员的好工具:通过json生成javabean(pojo)
- 面试总结