A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© keys 中级黑马   /  2015-3-20 22:21  /  1462 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

二、静态的应用

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

虽然可以通过建立ArrayTool的对象使用这些工具方法,对数组进行操作。
发现了问题:
1.对象是用于封装数据的,可是ArrayTool对象并未封装特有的数据
2.操作数组的每一个方法都没有用到ArrayTool对象中的特有数据
这时候就考虑,让程序更严谨,是不需要对象的,
可以将ArrayTool中的方法定义成静态方法

注意:将方法都静态后,可以方便于使用,但是该类还是可以被其他程序建立对象的。
为了更为严谨,强制让该类不能建立对象。可以通过将构造函数私有化完成。


class ArrayTool{
        private ArrayTool(){}
       
        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];
        }
       
        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];
        }
       
        public static void selectSort(int[] arr){
                for(int x=0;x<arr.length-1;x++){
                        for(int y=x+1;x<arr.lenggth;y++){
                                if(arr[x]>arr[y]){
                                       
                                }
                        }
                }
        }
        public static void bubbleSort(int[] arr){
                for(int x = 0;x<arr.lenggth-1;x++){
                        for(int y=0;y<arr.length-x-1;y++){
                                if(arr[y]>arr[y+1]){
                                        swap(arr,y,y+1);
                                }
                        }
                }
        }
        private static void sawap(int[] arr,int a,int b){
                int temp = arr[a];
                arr[a] = arr[b];
                arr[b] = temp;
        }
       
        public static void printArray(int[] arr){
                System.out.println("[");
                for(int x=0;x<arr.length;x++){
                        if(x!=arr.length-1)
                                System.out.println(arr[x]+", ");
                        else
                          System.out.println(arr[x]+"]");
                }
        }
       
}

class ArrayToolDemo{
        public static void main(String[] args){
                int[] arr = {3,4,5,6};
               
                /***********方法都定义成static后,这下面建立的对象就变得没意义了***
                ArrayTool tool  = new ArrayTool();
               
                int max = tool.getMax(arr);
                System.out.println("max="+max);
               
                int min = tool.getMin(arr);
                System.out.println("min="+min);
               
                tool.printArray(arr);
                tool.selectSort(arr);
                tool.printArray(arr);
               
                int[] arr1  = {};
                ArrayTool tool  = new ArrayTool();
                ******************************************************************/
               
                int max = ArrayTool.getMax(arr);
                System.out.println("max="+max);
        }
}

/*
一个类中默认会有一个空参数的构造函数,
这个默认的构造函数的权限和所属类一致。
如果类被public修饰,那么默认的构造函数也带有public修饰符。

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


三、静态代码块
格式:
static{
        静态代码块中的执行语句
}
特点:随着类的加载而执行,只执行一次,并优先于主函数
作用:用于类的初始化

例子一:
class StaticCode{
        static{
                System.out.println("a");
        }
               
}


class StaticCodeDemo{
        static{
                System.out.println("a");
        }       

        public static void main(String[] args){
                new StaticCode();
                new StaticCode();
                System.out.println("over");
        }
       
        static{
                System.out.println("a");
        }       
}

执行java StaticCodeDemo命令后;
打印顺序:b c a over

例子二:
class StaticCode{
        static{
                System.out.println("a");
        }
        public static void show(){
                System.out.println("show run");
        }       
}


class StaticCodeDemo{
        static{
                //System.out.println("a");
        }       

        public static void main(String[] args){
                //new StaticCode();
                //new StaticCode();
                //System.out.println("over");
                //StaticCode.show();
                StaticCode s =null;//这是a没执行,因为这样类没有被加载
                s = new StaticCode(); //用到类的内容,才能被加载,所以a也没调用
               
        }
       
        static{
                System.out.println("a");
        }       
}

例子三:


class StaticCode{
        int num = 9;

        StaticCode(){
                System.out.println("b");
        }
        static{
                System.out.println("a"+this.num);//问题2:会报错,因为静态代码块不允许访问非静态成员变量
        }
       
        {
                System.out.println("c"+this.num);//问题3:这样不会报错
        }
        StaticCode(int x){
                System.out.println("d");
        }
        public static void show(){
                System.out.println("show run");
        }       
}


class StaticCodeDemo{
        static{
                //System.out.println("a");
        }       

        public static void main(String[] args){
                new StaticCode(4); //问题1.打印的顺序是a c d(调用带参的构造函数),b没有打印
               
        }
       
        static{
                System.out.println("a");
        }       
}

四:对象的初始化过程       

该句话都做了什么事情?
1.因为new用到了Person.class,所以先找到Person.class文件并加载到内存中。
2.执行该类中的static代码块,如果有的话,给Person.class类进行初始化。
3.在对内存中开辟空间,分配内存地址。
4.在堆内存中建立对象的特有属性,并进行默认初始化。
5.对属性进行显示初始化。
6.对对象进行构造代码块初始化。
7.对对象进行相应的构造函数初始化。
8.将内存地址付给栈内存中的p变量

五:对象调用成员过程
问题1:
class Person{
        private String name ;
        private int age;
        private static String country = "cn";
        Person(String name,int age){
                this.name = name;
                this.age = age;
        }
        public void setName(String name){
                this.name  = name;
        }
        public void speak(){
                System.out.println(this.name+".."+this.age);
        }
        public static void showCountry(){
                System.out.println("country="+country);
        }

}

分析:Person p = new Person("zhangsan",20); //先给name赋值name=zhangsan;
          p.setName("lisi"); //这是name=lisi,因为p调用setName,那么this就是指向p

  
问题2:静态方法之间互调省略了类名. 而非静态之间方法之间互调省略了this.
  class Person{
        private String name ;
        private int age;
        private static String country = "cn";
        Person(String name,int age){
                this.name = name;
                this.age = age;
        }
        public void setName(String name){
                this.name  = name;
        }
        public void speak(){
                System.out.println(this.name+".."+this.age);
        }

        public static void showCountry(){
                System.out.println("country="+Person.country); //Person.可以省略
                Person.method();
        }
       
        public static void method(){
                System.out.println("method run");
        }
}

六、拓展部分(设计模式)

java中有23种设计模式
单例设计模式:解决一个类在内存中只存在一个对象。

想要保证对象唯一。
1.为了避免其他程序过大建立该类对象,先禁止其他程序建立该类对象。
2.还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。
3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。

这三部怎么用代码体现呢?
1.将构造函数私有化
2.在类中创建一个本类对象。
3.提供一个方法可以获取到该对象。



class Single{
        private int num;
        public void setNum(int num){
                this.num = num;
        }
        public void getNum(){
                return num;
        }
        /*例子二*/
        private Single(){}
       
        /*例子一:
        Single(){}*/
       
        static Single s = new Single();
               
        public static Single getInstance(){
                return s;
        }

}

class SingleDemo{
        public static void main(String[] args){
       
                Single s1 = Single.getInstance();
                Single s2 = Single.getInstance();
               
                s1.setNum(23);
                System.out.println(s2.getNum());
       
                /*
                例子一:
                Single s1 = new Single();
                Single s2 = new Single();
                s1.setNum(30);
                System.out.println(s2.getNum());//值为0,因为不是单例*/
               
                Student s1 = Student.getStudent();
                Student s2 = Student.getStudent();
        }
}

对于事物该怎么描述,还怎么描述。
当需要将该事物的对象保证在内存中唯一时,就将以上的三步加上即可,如下:

class Student{
        private int age;
        private static Student s = new Student();
        private Student(){}
       
        public static Student getStudent(){
                return s;
        }
       
        public void setAge(int age){
                this.age = age;
               
        }
        public int getAge(){
                return age();
        }
}
  
  
单例的两种写法:

第一种写法:
这个是先初始化对象。
称为:饿汉式。
特点:Single类一进内存,就应经创建好了对象。
/*class Single{
        private static Single s = new Single();
        private Single(){}
        public static Single getInstance(){
                return s;
        }
       
}*/


第二种写法:
对象呗调用的时候,才初始化,也叫做对象的延时加载。
称为:懒汉式。
//Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象
class Single{
        private static Single s = null;
        private Single(){}
        public static  Single getInstance(){
                if(s==null){
                        synchronized(Single.class){
                                if(s==null)
                                s = new Single();
                        }
                }
                return s;
        }
       
}
记住原则:定义单例,建议使用饿汉式
面试时,考的最多是懒汉式,要理解

2 个回复

倒序浏览
单例模式点赞
回复 使用道具 举报
赞一个!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马