------- android培训、java培训、期待与您交流! ----------
static关键字以及静态
用途:是一个修饰符,只能用于修饰成员(成员变量和成员函数)。不能修饰局部变量。 被修饰后的成员具备一下特点:
随着类的加载而加载,随着类的消失而消失。 优先于对象存在。 被所有对象所共享。(任意一个对象更改了静态数据,那么其他对象使用数据时使用的就是更改后的数据。) 不仅可以被对象调用,并且可以直接被类名调用。格式:类名.静态成员 被static修饰的成员不在堆内存里,而是在方法区。 静态使用的注意事项:
静态方法只能访问静态成员,非静态方法既能访问非静态又可以访问非静态。 静态中不能使用this和super等关键字。因为静态是随类的加载而加载,优先于对象的存在。而this和super指的是对象。 主函数是静态的。 实例变量和类变量(被static修饰的变量)的区别
存放的位置
类变量:随着类的加载而加载,存在于方法区中。 实例变量:随着对象的建立而建立,存在于堆内存中。 生命周期:
类变量:生命周期最长,随着类的消失而消失。 实例变量:随着对象的消失而消失。 静态的利弊:
好处:对对象的共享数据进行单独空间存贮,节省空间。 弊端:
生命周期过长 访问出现局限性,只能访问静态成员。 注意:静态不能用于修饰局部变量,因为局部变量只在定义他的那个方法或者代码块中有效。但是如果被静态修饰,则只有类消失时,该变量才会消失。 什么时候定义静态变量(类变量)?
当对象中出现共享数据时,该数据被静态所修饰。如所有的中国人的国籍。 什么时候定义静态函数呢?
当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定成静态的。 静态方法的应用:
每一个应用程序中都有共性的功能,可以把这个功能进行抽取,独立封装形成一个只含有静态方法的类以便复用。(但是将方法静态后,该类还是可以被其他程序建立对象,为了更加严谨,可以强制让该类不能建立对象。方法是私有化构造函数) 代码诠释(将前面的操作数组的函数可以改写成以下代码,以提高代码的复用性)
class ArrayTool { // 私有空参数构造函数,防止建立对象 private ArrayTool(){} // 给int数组进行选择排序。 public static int[] selectSort(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); } } } return arr; } private static void swap(int[] arr,int a,int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } // 用于打印数组中的元素。打印形式是:[elemet1, element2, ...] public static void printArray(int[] arr) { System.out.print("["); for(int x=0; x<arr.length; x++) { if(x!=arr.length-1) System.out.print(arr[x]+", "); else System.out.println(arr[x]+"]"); } } } class Arr { public static void main(String[] args) { int[] a = {1,4,66,5,76,8}; ArrayTool.printArray(a);//打印原数组 ArrayTool.printArray(ArrayTool.selectSort(a));//打印排序过后的数组 } }
-
代码分析:
-
将操作数组的工具类独立封装成一个类,因为其中的方法没有操作任何该类的特有数据,并且为了能方便调用,因此用静态修饰其中的函数。当调用的时候,只需通过类名调用就可以了。
-
-
main函数
主函数的含义
是一个特殊的函数,作为程序的入口,可以被jvm调用。 主函数定义详解:jvm的格式是固定的,只有这样才能被jvm识别。
public:代表着该函数访问权限是最大的。 static:代表主函数随着类的加载就已经存在了。 void:主函数没有具体的返回值。 main:不是关键字,但是是一个特殊的单词,可以被jvm识别。 (String[] args):函数的参数,参数的类型是一个数组,该数组中的元素是字符串,即字符串类型的数组。 jvm在调用主函数时,传入的是new String[0] 主函数传值的例子:class MainDemo { public static void main(String[] args)//new String[] { System.out.println(args[0]); System.out.println(args[1]); } }
Dos命令行中执行以下命令:
在这个程序中,在执行的时候往args数组中传了三个字符串“你好”“我好”“大家好”,在程序中只让打印出前面两个,所以打印出了“你好”“我好”。帮助文档
需求:当开发的工具编译后生成一个工具包,把这个包发给给别人使用,但是使用者又不知道如何使用,此时便需要制作程序说明书。 制作工具:JAVA的说明书通过文档注释来完成,通过javadoc命令来完成。 制作帮助文档的前提:
该类必须有足够大的权限即被public修饰。 只有被public或者protected修饰的才能被javadoc提取。 默认的空参数构造函数和类的权限一样,如果类被public修饰,那么默认的构造函数也被public修饰。如果类没有被public修饰,则默认的构造函数也没有被public修饰。 制作格式以及常用的命令:/** 对此工具类的说明,即提供了什么功能 @author 开发者姓名 @version 版本 @param 参数 @return 返回什么 */
javadoc命令的使用:
javadoc -d 文件夹,当没注明路径时即在当前目录下-author-version(这两个参数及说明是否显示版本和作者)源文件名.java 代码诠释:/** 这是一个可以对数组进行操作的工具类,该类中提供了,获取最值,排序等功能。 @author 传智播客学员 @version V1.1 */ public class ArrayTool { /** 空参数构造函数。 */ private ArrayTool(){} /** 获取一个整形数组中的最大值。 @param arr 接收一个int类型的数组。 @return 会返回一个该数组中最大值。 */ 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]; } /** 获取一个整形数组中的最小值。 @param arr 接收一个int类型的数组。 @return 会返回一个该数组中最小值。 */ public static int getMin(int[] arr) { int min = 0; for(int x=1; x<arr.length; x++) { if(arr[x]<arr[min]) min = x; } return arr[min]; } /** 给int数组进行选择排序。 @param arr 接收一个int类型的数组。 */ public static void selectSort(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数组进行冒泡排序。 @param arr 接收一个int类型的数组。 */ public static void bubbleSort(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); } } } } /** 给数组中元素进行位置的置换。 @param arr 接收一个int类型的数组。 @param a 要置换的位置 @param b 要置换的位置 */ private static void swap(int[] arr,int a,int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } /** 用于打印数组中的元素。打印形式是:[elemet1, element2, ...] */ public static void printArray(int[] arr) { System.out.print("["); for(int x=0; x<arr.length; x++) { if(x!=arr.length-1) System.out.print(arr[x]+", "); else System.out.println(arr[x]+"]"); } } }
静态代码块
格式:static { 静态代码块中的执行语句。 }
特点:
随着类的加载而加载,只执行一次。用于给类进行初始化的。
对象建立的过程:
- 图示:
代码诠释:
代码分析:class StaticCode { int num = 9;//成员变量 //静态代码块 static { System.out.println("e"); //this.num = 8; //System.out.println("执行静态代码块儿 num = "+this.num); } //构造代码块 { num = 7; System.out.println("执行构造代码块 num = "+num); } //有一个整型变量的构造函数 StaticCode(int x) { this.num = x; System.out.println("执行构造函数 num = "+num); } } class StaticCodeDemo { //主函数 public static void main(String[] args) { new StaticCode(4); } //静态代码块 static { System.out.println("a"); } } /* 执行结果 ============================ a e 执行构造代码块 num = 7 执行构造函数 num = 4 ============================ */主函数的类先
首先是主函数所在类加载被加载,类一被加载静态代码块执行,所以打印出a,然后是主函数开始执行。创建一个StaticCode的对象,所以StaticCode类被加载,类被加载后执行静态代码块,所以又打印出e,然后是执行构造代码块将7赋值给num,对属性进行初始化,所以接着打印出第三句。最后执行构造函数对对象进行赋值。所以最终num的值是4.
对象的调用过程:单例设计模式
设计模式:解决某一类问题最行之有效的方法。 单例设计模式:解决一个类在内存中只有一个对象。 该模式的思想:
为了避免其他程序过多的建立该类对象,先禁止其他程序建立该类对象。 为了让其他程序可以访问到该类对象,则在本类中自定义一个对象。 为了方便其他程序对自定义对象的访问,可以提供一些访问方式。 代码如何实现:
防止建立新的对象——将构造函数私有化。 创建一个对象供其他程序调用——在本类中创建一个本类对象。
此时创建的这个 对象相当于类的一个属性,为了提高安全性则必须将其私有化。 方便其他程序对自定义对象的访问——提供一个方法可以获取该对象。
方法必须有对象或者类调用,然而其他程序不能建立新的对象,所以不能由对象调用。只能由类名调用,因此得把该方法定义成静态的。- 单例设计模式的两种模式:
- 饿汉式:在类一加载的时候,就初始化一个对象。
- 代码:
class Single { private Single(){} private static Single s = new Single(); public static Single getSingle() { return s; } } class SingleDemo { public static void main(String[] args) { Single s1 = Single.getSingle(); Single s2 = Single.getSingle(); if (s1.equals(s2)) System.out.println("同一个对象"); else System.out.println("不是同一个对象"); } }
执行结果是“同一个对象”- 懒汉式:类进内存,对象还没有存在,只有调用获取对象方法时,才建立对象。
class Single { private Single(){} private static Single s = null; public static Single getSingle() { if(s==null) //① s = new Single(); return s; } } class SingleDemo { public static void main(String[] args) { Single s1 = Single.getSingle(); Single s2 = Single.getSingle(); if (s1.equals(s2)) System.out.println("同一个对象"); else System.out.println("不是同一个对象"); } }
对于懒汉式如果一个人使用没有问题,但是如果多个人使用这个程序时,就会出现安全问题。比如:两个人都在使用这个程序,如果第一个人调用时,在①处CPU切换到另外一个人,再进行判断时。s还是为空,这样第一个人和第二个人的都会创建一个对象。所以要将代码进行如下优化。class Single { private Single(){} private static Single s = null; public static Single getSingle() { if (s==null) //先判断引用是不是为空 { synchronized(Single.class)//防止第一次创建对象时多个人调用,产生安全问题 { if(s==null) //① s = new Single(); } } return s; } } class SingleDemo { public static void main(String[] args) { Single s1 = Single.getSingle(); Single s2 = Single.getSingle(); if (s1.equals(s2)) System.out.println("同一个对象"); else System.out.println("不是同一个对象"); } }
在以上的这两种方法中,开发中最常用的是饿汉式。因为简单并且不会产生安全问题,但是将懒汉式进行双重判断和加上锁机制以后也可以解决这个问题。加上双重判断主要是为了第二次执行的时候不再去判断锁,提高了程序的执行效率。