疯狂JAVA讲义---第六章(上):面向对象二

时间:2021-12-15 16:24:48

面向对象是java的重点,所以也是这本书的重点。这章延续上章,我粗略数了下,这两张加起来竟然达到这本书的四分之一。这章刚开始讲了包装类,由于jdk1.5以后引入了自动装箱和拆箱,基本类型和包装类转化就方便了。包装类有很多方法用起来很方便大家要熟悉下,eg

  1. public class Primitive2String
  2. {
  3.     public static void main(String[] args) 
  4.     {
  5.         String intStr = "123";
  6.         //把一个特定字符串转换成int变量
  7.         int it = Integer.parseInt(intStr);
  8.         System.out.println(it);
  9.         String floatStr = "4.56";
  10.         //把一个特定字符串转换成float变量
  11.         float ft = Float.parseFloat(floatStr);
  12.         System.out.println(ft);
  13.         //把一个float变量转换成String变量
  14.         String ftStr = String.valueOf(2.345f);
  15.         System.out.println(ftStr);
  16.         //把一个double变量转换成String变量
  17.         String dbStr = String.valueOf(3.344);
  18.         System.out.println(dbStr);
  19.         //把一个boolean变量转换成String变量
  20.         String boolStr = String.valueOf(true);
  21.         System.out.println(boolStr.toUpperCase());
  22.     }
  23. }

网上说的很多关于==和equals的区别,误导了一大片人,看了李刚的书,然后我也研究了下jdk的源码。发现对object来说这两者是一样的。下面看源码

  1.  public boolean equals(Object obj) {
  2.     return (this == obj);
  3.     }

 

网上说了很多他们之间的不同是由于(我们那String来做例子)equals被重写过,eg

  1.   public boolean equals(Object anObject) {
  2.     if (this == anObject) {
  3.         return true;
  4.     }
  5.     if (anObject instanceof String) {
  6.         String anotherString = (String)anObject;
  7.         int n = count;
  8.         if (n == anotherString.count) {
  9.         char v1[] = value;
  10.         char v2[] = anotherString.value;
  11.         int i = offset;
  12.         int j = anotherString.offset;
  13.         while (n-- != 0) {
  14.             if (v1[i++] != v2[j++])
  15.             return false;
  16.         }
  17.         return true;
  18.         }
  19.     }
  20.     return false;
  21.     }

然后讲了设计模式中的单例模式(具体我会在以后的设计模式中讲)现在先举个例子,eg

  1. class Singleton
  2. {
  3.     //使用一个变量来缓存曾经创建的实例
  4.     private static Singleton instance;
  5.     //将构造器使用private修饰,隐藏该构造器
  6.     private Singleton(){}
  7.     //提供一个静态方法,用于返回Singleton实例
  8.     //该方法可以加入自定义的控制,保证只产生一个Singleton对象
  9.     public static Singleton getInstance()
  10.     {
  11.         //如果instance为null,表明还不曾创建Singleton对象
  12.         //如果instance不为null,则表明已经创建了Singleton对象,将不会执行该方法
  13.         if (instance == null)
  14.         {
  15.             //创建一个Singleton对象,并将其缓存起来
  16.             instance = new Singleton();
  17.         }
  18.         return instance;
  19.     }
  20. }
  21. public class TestSingleton
  22. {
  23.     public static void main(String[] args)
  24.     {
  25.         //创建Singleton对象不能通过构造器,只能通过getInstance方法
  26.         Singleton s1 = Singleton.getInstance();
  27.         Singleton s2 = Singleton.getInstance();
  28.         //将输出true
  29.         System.out.println(s1 == s2);
  30.     }
  31. }

不可变类的设计,注意引用变量的问题。eg

  1. class Name
  2. {
  3.     private String firstName;
  4.     private String lastName;
  5.     public Name(){}
  6.     public Name(String firstName , String lastName)
  7.     {
  8.         this.firstName = firstName;
  9.         this.lastName = lastName;
  10.     }
  11.     public void setFirstName(String firstName)
  12.     {
  13.         this.firstName = firstName;
  14.     }
  15.     public String getFirstName()
  16.     {
  17.          return this.firstName;
  18.     }
  19.     public void setLastName(String lastName)
  20.     {
  21.         this.lastName = lastName;
  22.     }
  23.     public String getLastName()
  24.     {
  25.          return this.lastName;
  26.     }
  27. }

这里虽然没改person对象,但其实改name对象的时候,由于name对person是引用对象,所以person中的name其实也是改变了,为了解决这个问题,使用以下方法。eg

public class Person {     private final Name name;     public Person(Name name)     {         //this.name = name;         this.name = new Name(name.getFirstName(), name.getLastName());     }     public Name getName()     {         //return name;         return new Name(name.getFirstName(), name.getLastName());     }     public static void main(String[] args)     {         Name n = new Name("悟空""孙");         Person p = new Person(n);         //如果没有保护:Person对象的Name属性的firstName属性值为"悟空"         System.out.println(p.getName().getFirstName());         //改变Person对象Name属性的firstName属性值         n.setFirstName("八戒");         //如果没有保护:Person对象的Name属性的firstName属性值为"八戒"         System.out.println(p.getName().getFirstName());     } }

虽说还是引用对象但这个name对象别人访问不到了,这样就实现了不可变类。

最后讲个用缓存来实现不可变类,eg

public class CacheImmutale {     private final String name;     private static CacheImmutale[] cache = new CacheImmutale[10];     //记录缓存实例在缓存中的位置,cache[pos-1]是最新缓存的实例     private static int pos = 0;     public CacheImmutale(String name)     {         this.name = name;     }     public String getName()     {         return name;     }     public static CacheImmutale valueOf(String name)     {         //遍历已缓存的对象,         for (int i = 0 ; i < pos; i++)         {             //如果已有相同实例,直接返回该缓存的实例             if (cache[i] != null && cache[i].getName().equals(name))             {                 return cache[i];             }         }         //如果缓存池已满         if (pos == 10)         {             //把缓存的第一个对象覆盖             cache[0] = new CacheImmutale(name);             //把pos设为1             pos = 1;             return cache[0];         }         else         {             //把新创建的对象缓存起来,pos加1             cache[pos++] = new CacheImmutale(name);             return cache[pos - 1];               }     }     public boolean equals(Object obj)     {         if (obj instanceof CacheImmutale)         {             CacheImmutale ci = (CacheImmutale)obj;             if (name.equals(ci.getName()))             {                 return true;             }         }         return false;     }     public int hashCode()     {         return name.hashCode();     }     public static void main(String[] args)     {         CacheImmutale c1 = CacheImmutale.valueOf("hello");         CacheImmutale c2 = CacheImmutale.valueOf("hello");         //下面代码将输出true         System.out.println(c1 == c2);     } }