7-16笔记-面向对象之对象和类

7月16号笔记

今天的主要内容:

  • 对象和类的学习——联系类的构造技巧
  • 数组学习——for-each
  • LocalDate的学习
  • 关键字的学习——final/static/this
  • 工厂方法的学习【重点】
  • 类的设计技巧

1. 数组的学习

  • 数组定义:

    int[] arr = new int[]{1,3,5,8,9,11};

  • java.util.Arrays类的使用

    • Arrays.toString(type[] a);

    • Arrays.copyOf(type[] a,int length);

    • Arrays.sort(type[] a);

  • TestArray

    import java.util.Arrays;

    public class TestArray{
        public static void main(String[] args){
            
            //数组的定义:
            int[] arr = new int[]{1,3,5,8,9,11};
            
            //Arrays.toString(type[] a);
            String arrString = Arrays.toString(arr);
            System.out.println("arr : " + arrString);
            
            //Arrays.copyOf(type[] a,int length);
            int[] b = Arrays.copyOf(arr,arr.length);
            
            //Arrays.sort(type[] a)
            Arrays.sort(b);
            
            //for-each遍历数组
            System.out.print("After sort : ");
            for(int element:b){
                System.out.print(element + "  ");
            }
            
            System.out.println("\n");
        }
    }
    /*
    在JDK1.8中输出结果为:
    -------------------------------
    arr : [1, 3, 5, 8, 9, 11]
    After sort : 1  3  5  8  9  11
    -------------------------------
    */

2. java.time.LocalDate类

import java.time.LocalDate;

public class TestLocalDate{
    public static void main(String[] args){
        //LocalDate date1 = new LocalDate();   不正确
        //此时用静态工厂方法代表调用的构造器

        LocalDate date = LocalDate.now();       
        System.out.println("The LocalDate : " + date);
        
        LocalDate date2 = LocalDate.of(2018,7,16);
        System.out.println("The LocalDate : " + date2);
        
        //LocalDate类中的方法学习
        int dayOfYear = date.getDayOfYear();   
        int dayOfMonth = date.getDayOfMonth();  
        int month = date.getMonthValue();
        int year = date.getYear();
        
        System.out.println("getDayOfYear() : " + dayOfYear 
                + "\ngetDayOfMonth() : " + dayOfMonth 
                + "\ngetMonthValue() : " + month 
                + "\ngetYear() : " + year);             
    }
}

/*
    在JDK1.8中输出结果为:
    ------------------------------------
    The LocalDate : 2018-07-16
    The LocalDate : 2018-07-16
    getDayOfYear() : 197                            //按照阴历计算
    getDayOfMonth() : 16
    getMonthValue() : 7
    getYear() : 2018
    ------------------------------------
*/

3. 对象和类的理解

  1. Employee类

    • data field:

      • name,salary,hireDay
    • method:

      • getName();
      • getSalary();
      • gethireDay();
    • class Employee

        import java.time.LocalDate;
        
        class Employee{
            
            //data field
            private String name;
            private double salary;
            private LocalDate hireDay;
            
            //constructor
            public Employee(String name,double salary,int year,int month,int day){
                this.name = name;
                this.salary = salary;
                this.hireDay = LocalDate.of(year,month,day);
            }
            
            //method
            public String getName(){
                return name;    
            }
            
            public double getSalary(){
                return salary;  
            }
            
            public LocalDate gethireDay(){
                return hireDay;
            }
            
            public void raiseSalary(double byPercent){
                salary += salary * byPercent/100;
            }
        }
      
  2. EmployeeTest类

     public class EmployeeTest{
         public static void main(String[] args){
             Employee[] staff = new Employee[3];
             
             staff[0] = new Employee("zhangsan",100,2018,7,9);
             staff[1] = new Employee("lisi",200,2018,7,16);
             staff[2] = new Employee("hahaha",300,2018,7,23);
             
             System.out.println("=====================所有员工信息======================");
             
             //raise everyone's salary by 5%
             for(Employee e : staff){
                 e.raiseSalary(5);
             }
             
             //输出所有员工信息
             for(Employee e : staff){
                 System.out.println("name : " + e.getName()
                 + "  salary : " + e.getSalary()
                 + "  hiredate : " + e.gethireDay()
                 );      
             }
         }   
     }
     /*
         在JDK1.8中输出结果为:
         ---------------------------------------------------------
         =====================所有员工信息======================
         name : zhangsan  salary : 105.0  hiredate : 2018-07-09
         name : lisi  salary : 210.0  hiredate : 2018-07-16
         name : hahaha  salary : 315.0  hiredate : 2018-07-23
         ---------------------------------------------------------
     */
    

4. 关键字的学习

  1. final

    • final修饰实例域(data field)时
      • 确保在每一个构造器执行后,这个域的值被设置
      • 在后面操作中,不能够再对它进行修改
      • 例如在Employee类中name域声明为final
      •   class Employee{
              private final String name;
              
              ....
          }   
        
    • final关键字只是表示对象的引用不会再指示其他对象
  2. static

    • static修饰实例域时,每个类中只有一个这样的域
      • 给每一个雇员一个标识码

          class Employee{
              private static nextID;
              private int id;
          }
        
      • 此时这个类的所有实例共享nextID域,静态域属于类,不属于任何独立的对象

* static修饰静态常量时,例如:

         public class Math{
            public static final double PI = 3.141592653.....;
         }
    * 此时可通过类名直接使用PI常量:Math.PI;
    
* static修饰方法时,表示静态方法是一种不能向对象实施操作的方法
    * 静态方法不可以访问非静态的
    * 非静态的可以访问静态的
  1. this

    • this指示隐士参数,也就是所构造的对象

        public Employee(String name,double salary){
            this.name  = name;
            this.salary = salary;
        }
      
      • this指的是当前对象
    • this调用另一个构造器
      public Employee(double s){
      //calls Employee(String,double)
      this("Employee #" + nextID.s);
      nextID++;
      }

5. 工厂方法的学习

  • 使用场景

    • 在任何需要生成复杂对象的地方,可以直接new的不需要工厂模式,也就是,当使用构造器无法改变所构造的类型时。
    • 需要生成的对象叫做产品,生成对象的地方叫做工厂。
  • 例1:吃水果时需要区分不同水果类————课堂例子

    • 创建Fruit接口,定义水果eat规范

        interface Fruit{
            public void eat();
        }
      
    • 创建Apple和Orange两类,继承接口,实现抽象方法eat

        class Apple implements Fruit{
            public void eat(){
            System.out.println("吃苹果");
            }
        }
        
        class Orange implements Fruit{
            public void eat(){
                System.out.println("吃橘子");
            }   
        }
      
    • 创建工厂,生产两产品

        class Factory{
            public static Fruit getFruit(String name){
                if(name.equals("apple")){
                    return new Apple(); 
                }
                else if(name.equals("orange")){
                    return new Orange();    
                }   
                else{
                    return null;
                }
            }
        }
      
    • 测试工厂类

        public class Test{
            public static void main(String[] args){
            Factory.getFruit(args[0]).eat();
            }
        }
      
        /*
            此时程序不严谨,当输入的参数不是apple和orange时抛出java.lang.NullPointerException
        */      
      
      • 此时的工厂可做到需要什么取什么,而我们不需要知道内在如何完成。

5.1 系统学习工厂模式

一. 简单(静态)工厂

一个例子:

喜欢吃水果,此时抽象一个水果类或者接口,此时这就是产品的抽象类

abstract class Fruit{
    /*
    描述说过什么样,有多好吃    
    */

    public abstract void desc();
}

先尝尝苹果(具体的产品类)

class AppleFruit extends Fruit{
    @Override           
    public void desc(){
        System.out.println("苹果好吃还便宜,嘻嘻嘻");
    }
}

再试试橘子(具体的产品类)

class OrangeFruit extends Fruit{
    @Override           
    public void desc(){
        System.out.println("橘子好久没吃了,有点酸");
    }
}

还有我最爱吃的榴莲(具体的产品类)

class DurianFruit extends Fruit{
    @Override           
    public void desc(){
        System.out.println("榴莲我觉得很好吃啊");
    }
}

准备工作做完了,我们来到一家“简单水果店”(简单工厂类),菜单如下:

class SimpleFruitFactory{
    public static final int TYPE_APPLE = 1; //苹果
    public static final int TYPE_ORANGE = 2; //橘子
    public static final int TYPE_DURIAN = 3; //榴莲

    public static Fruit createFruit(int type){
        switch(type){
            case TYPE_APPLE:
                return new AppleFruit();
            case TYPE_ORANGE:
                return new OrangeFruit();
            case TYPE_DURIAN:
                return new DurianFruit();
        }
    }
}

简单的水果店就提供三种水果(产品),你说你要啥,他就给你啥。这里我买了一个榴莲:

/*
    简单工厂模式
*/

public class Test{  
    public static void main(String[] args){
        Fruit fruit = SimpleFruitFactory.createFruit(SimpleFruitFactory.TYPE_DURIAN);
        fruit.desc();
    }   
}

在JDK1.8中输出结果为:

    ------------------
    榴莲我觉得很好吃啊
    ------------------- 
简单(静态)工厂特点
  • 它是一个具体的类,非接口 抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回。

  • create()方法通常是静态的,所以也称之为静态工厂。

简单(静态)工厂缺点
  • 扩展性差(我想增加一种面条,除了新增一个面条产品类,还需要修改工厂类方法)

  • 不同的产品需要不同额外参数的时候 不支持,因为switch的原因

二. 多方法工厂(常用)

  • 多方法的工厂模式为不同产品,提供不同的生产方法,使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高。

  • 水果工厂类

      class MulWayFruitFactory{
      
          /*
              吃苹果
          */
          public static Fruit createApple(){
              return new AppleFruit();
          }
          
          /*
              吃橘子
          */
          public static Fruit createOrange(){
              return new OrangeFruit();
          }
          
          /*
              吃榴莲
          */
          public static Fruit createDurian(){
              return new DurianFruit();
          }
      }
          
      //测试
      public class Test{
          
          public static void main(String[] args){
              Fruit fruit = MulWayFruitFactory.createApple();
              fruit.desc();
          }   
      }
    
    • 多方法工厂一个好处在于,只需要创建产品类以及在工厂类中添加static方法即可

三. 普通工厂(常用)

  • 普通工厂就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层+具体的工厂子类层。(一般->特殊)

水果生产工厂(抽象工厂类),作用就是生产水果

abstract class FruitFactory{
    public abstract Fruit create();
}

苹果工厂(具体工厂类)

class AppleFactory extends FruitFactory{
    @Override
    public Fruit create(){
        return new AppleFruit();
    }
}

橘子工厂(具体工厂类)
class OrangeFactory extends FruitFactory{
@Override
public Fruit create(){
return new OrangeFruit();
}
}
榴莲工厂(具体工厂类)
class DurianFactory extends FruitFactory{
@Override
public Fruit create(){
return new DurianFruit();
}
}
测试:

public class Test{
    public static void  main(String[] args){
        FruitFactory factory = new OrangeFactory();
        
        factory.create().desc();
    }
}

/*
    在JDK1.8中输出结果为:
    ----------------------
    橘子好久没吃了,有点酸
    ----------------------
*/

普通工厂和简单工厂区别:

  • 普通工厂模式特点:不仅仅做出来的产品要抽象, 工厂也应该需要抽象。
  • 工厂方法使一个产品类的实例化延迟到其具体工厂子类.
  • 工厂方法的好处就是更拥抱变化。当需求变化,只需要增删相应的类,不需要修改已有的类。
  • 而简单工厂需要修改工厂类的create()方法,多方法静态工厂模式需要增加一个静态方法。
  • 引入抽象工厂层后,每次新增一个具体产品类,也要同时新增一个具体工厂类

此工厂方法的理解转载自https://blog.csdn.net/zxt0601/article/details/52798423#commentBox

6. 块优先级的学习

  • Employee类

      import java.time.LocalDate;
      import java.util.Random;
    
      class Employee{
          private static int nextID;
          
          //data field
          private int id;
          private String name = "";
          private double salary;
          
          //static块
          static{
              Random random = new Random();
              nextID = random.nextInt(10000);         
          }
          
          //普通块
          {
              id =nextID;
              nextID++;   
          }
          
          //三个重载方法
          public Employee(String name,double salary){
              this.name = name;
              this.salary = salary;   
          }
          
          public Employee(double salary){
              this("hahaha",salary);  
          }
          
          public Employee(){
                  
          }
          
          public String getName(){
              return name;
          }
          
          public double getSalary(){
              return salary;
          }
          
          public int getId(){
              return id;  
          }   
      }
    
  • EmployeeTest类

      public class EmployeeTest{
          public static void main(String[] args){
              Employee[] staff = new Employee[3];
              
              staff[0] = new Employee("zhangsan",100);
              staff[1] = new Employee(200);
              staff[2] = new Employee();
              
              //输出所有员工信息
              for(Employee e : staff){
                  System.out.println("name : " + e.getName()
                  + "  salary : " + e.getSalary()
                  + "  id : " + e.getId()
                  );      
              }
          }   
      }
    
      /*
          在JDK1.8中输出结果为:
          ---------------------------------------------------------
          name : zhangsan  salary : 100.0  id : 2269
          name : hahaha  salary : 200.0  id : 2270
          name :   salary : 0.0  id : 2271
          ---------------------------------------------------------
      */
    
      /*
          此时可看出优先顺序
          static > 普通块 
      */
    

7. 类设计技巧的学习

  1. 一定要保证数据私有

    • 绝对不能破坏封装性
    • 保持实例域的私有性
  2. 一定要对数据初始化

    • 不要依赖系统默认值
    • 显式的初始化所有的数据
    • 初始化方式
      • 提供默认值
      • 构造其中设置默认值
  3. 不要在类中使用过多的基本类型

    • 用其他的类代替多个相关的基本类型的使用
  4. 不是所有的域都需要独立的域访问器和域更改器

  5. 将职责过多的类进行分解

    • 也不要分解到过多
  6. 类名和方法名要能够体现他们的职责

  7. 优先使用不可变的类

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,621评论 18 399
  • 一、iBATIS介绍 iBATIS的是一个持久层框架,它能够自动在Java, .NET, 和Ruby on Rai...
    子非鱼_t_阅读 1,802评论 0 2
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,649评论 18 139
  • 每两年去验一次血,各项指标都正常。我喜欢喝饮料喜欢喝可乐,本来以为血糖会很高,可是结果出来并不高。但是尿液中老是有...
    笑傲江湖201710阅读 162评论 0 0
  • 今日体验,今天给宝马检查异响,由于前几天换过刹车片和刹车盘,一直以为是刹车片响,一上午拆了五遍,最后检查发现是过桥...
    任武科阅读 182评论 0 0