第六章.面向对象(下)

Posted lanshanxiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第六章.面向对象(下)相关的知识,希望对你有一定的参考价值。

Java 8增强的包装类:

8中基本数据类型——8中包装类:

byte                           Byte

short                          Short

int          Integer

long          Long

char         Character

float            Float

double        Double

boolean      Boolean

除了int和char例外,其余基本数据类型对应的包装类都是将其首字母大写

Java1.5提供了自动装箱(Autoboxing)和自动拆箱(AutoUnboxing)功能

  自动装箱:可以把一个基本类型变量直接赋值给对应的包装类变量,或赋值给Object变量。

  自动拆箱:允许直接把包装类对象直接赋值给一个对应的基本类型变量。

 1 public class AutoBoxingUnboxing{
 2     public static void main(String[] args){
 3         //直接把一个基本类型变量赋给Integer对象
 4         Integer inObj = 5;
 5         //直接把一个boolean类型变量赋给一个Object类型的变量
 6         Object boolObj = true;
 7         //直接把一个Integer对象赋给int类型的变量
 8         int it = inObj;
 9         if(boolObj instanceof Boolean){
10             //先把Object对象强制类型转换为Boolean类型,再赋值给boolean变量
11             boolean b = (Boolean) boolObj;
12             System.out.println(b);
13         }
14     }
15 }
View Code

  Java还提供了基本类型变量的包装类和字符串之间的转换:

    包装类(除了Character之外)提供了 parseXxx(String s)静态方法,可将字符串转换为基本数据类型

    String类提供了多个重载valueOf()方法,用于将基本类型转变为字符串

 1 public class Primitive2String{
 2     public static void main(String[] args){
 3         String intStr = "123";
 4         //把一个特定字符串转换成int变量
 5         int it1 = Integer.parseInt(intStr);
 6         int it2 = new Integer(intStr);
 7         System.out.println(it2);
 8         String floatStr = "4.56";
 9         //把一个特定字符串转换成float变量
10         float ft1 = Float.parseFloat(floatStr);
11         float ft2 = new Float(floatStr);
12         System.out.println(ft2);
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 }
View Code

    把基本类型转换为String类型,更简便的方法是:

      String intStr = 5 + "";

    包装类的实例可以与数值类型进行比较:

      Integer a = new Integer(6);

      //输出true

      System.out.println("6的包装类实例是否大于5.0:" + (a > 5.0));

 处理对象:

  Object类中的方法:

    1.toString():

      java中System.out.println(p);//p是Person类的一个引用,该语句等价于System.out.println(p.toString());

      java中所有对象都可以和字符串进行连接运算:String pStr = p + "";//等价于String pStr = p.toString() + “”;

      Object类提供的toString()方法总是返回该对象实现类的“类名 + @ + hashCode”,用户要自己重写Object类中的toString()方法来实现类的”自我描述”功能。

    2.==和equals()方法

      测试两个变量是否相等的两种方式:== 和 equals()

      若两个变量是基本类型变量,且都是数值类型(不一定要求数据类型严格相同),则只要两个变量的值相等,就将返回true;

      若两个变量是引用类型变量,只有它们指向同一个对象时,==判断才会返回true。==不可用于比较类型上没有父子关系的两个对象。

1 public class EqualTest{
2     public static void main(String[] args){
3         System.out.println("hello" == new EqualTest());
4     }
5 }
View Code

      Object类中的equals()方法和==没有任何区别,要求两个引用变量指向同一个对象才会返回true。若希望采用自定义的相等标准,需要重写。

      String类重写了equals()方法,判断两个字符串相等的标准是:只要两个字符串包含的字符序列相同,通过equals()比较将返回true,否则将返回false。

下面是一个重写了equals()方法的Person类:

 1 class Person{
 2     private String name;
 3     private String idStr;
 4     public Person(){}
 5     public Person(String name, String idStr){
 6         this.name = name;
 7         this.idStr = idStr;
 8     }
 9     
10     public String getIdStr(){
11         return idStr;
12     }
13     
14     //重写equals()方法
15     public boolean equals(Object obj){
16         //若两个对象为同一个对象
17         if(this == obj)
18             return true;
19         //只有当obj是Person对象
20         if(obj != null && obj.getClass() == Person.class){
21             Person personObj = (Person) obj;
22             //并且当前对象的idStr与obj对象的idStr相等时才可判断两个对象相等
23             if(this.getIdStr().equals(personObj.getIdStr()))
24                 return true;
25         }
26         return false;
27     } 
28 }
29 
30 public class OverrideEqualsRight{
31     public static void main(String[] args){
32         Person p1 = new Person("孙悟空", "1234");
33         Person p2 = new Person("孙悟空", "1234");
34         Person p3 = new Person("孙悟饭", "4321");
35         //p1和自身相比
36         System.out.println("p1和p1是否相等?" + p1.equals(p1));
37         //p1和p2的idStr相等,所以输出true
38         System.out.println("p1和p2是否相等?" + p1.equals(p2));
39         //p2和p3的idStr不相等,所以输出false
40         System.out.println("p2和p3是否相等?" + p2.equals(p3));
41     }
42 }
View Code

   这里判断obj是否为Person类的实例使用的是obj.getClass() == Person.class//使用了反射基础

   不适用instanceof运算符,是因为对于instanceof运算符而言,前操作数只要是后操作数的实例或其子类的实例时,都将返回true;而我们要判断两个对象是否是同一个类的

   实例,所以不能使用instanceof运算符。

单例(Singleton)类:

  一个类始终只能创建一个实例,则这个类被称为单例类:

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

final修饰符:

  final关键字可用于修饰类、变量和方法,表示它修饰的类、方法和变量不可改变。

  final修饰变量,一旦该变量获得了初始值就不可被改变

  java程序规定:final修饰的成员变量必须有程序员显式地指定初始值,系统不会对final成员进行隐式初始化,不要再未初始化final成员前,访问final成员

 1 public class FinalErrorTest{
 2     //定义一个final修饰的实例变量
 3     //系统不会对final成员变量进行默认初始化
 4     final int age;
 5     {
 6         //age没有初始化,所以此处代码将引起错误
 7         System.out.println(age);
 8         age = 6;
 9         System.out.println(age);
10     }
11     
12     public static void main(String[] args){
13         new FinalErrorTest();
14     }
15 }
View Code

  final修饰的类变量、实例变量:

    类变量:必须在静态初始化块中指定初始值或生命该类变量时指定初始值,二选一

    实例变量:必须在非静态初始化块、声明该实例变量或构造器中指定初始值,三选一

 1 public class FinalVariableTest{
 2     //定义成员变量是指定初始值,合法
 3     final int a = 6;
 4     //下面变量将在构造器或初始化块中分配初始值
 5     final String str;
 6     final int c;
 7     final static double d;
 8     //既没有指定初始值,有没有在初始化块、构造器中指定初始值
 9     //下面定义的ch实例变量是不合法的
10     final char ch;
11     //初始化块,可对没有指定初始值的实例变量指定初始值
12     {
13         //在初始化块中为实例变量指定初始值,合法
14         str = "hello";
15         //定义a实例变量时已经指定了默认值
16         //不能为a重新赋值,因此下面赋值语句非法
17         a = 9;
18     }
19     //静态初始化块,可对没有指定初始值的类变量指定初始值
20     static{
21         //在静态初始化块中为类变量指定初始值,合法
22         d = 5.6;
23     }
24     //构造器中,可对没有指定初始值,有没有在初始化块中
25     //指定初始值的实例变量指定初始值
26     public FinalVariableTest(){
27         //若在初始化块中已经对str指定了初始值
28         //那么在构造器中不能对final变量重新赋值,下面的赋值语句非法
29         str = "java";
30         c = 5;
31     }
32     public void changeFinal(){
33         //普通方法不能为final修饰的成员变量赋值
34         d = 1.2;
35         //不能在普通方法中为final成员变量指定初始值
36         ch = \'a\';
37     }
38     public static void main(String[] args){
39         FinalVariableTest ft = new FinalVariableTest();
40         System.out.println(ft.a);
41         System.out.println(ft.c);
42         System.out.println(ft.d);
43     }
44 }
View Code

  final修饰的方法:

    不可被重写

  final修饰的类:

    不可被继承

    不可变类:创建该类的实例后,该实例的实例变量是不可改变的。Java提供的8个包装类和Java.lang.String类都是不可变类。

    final修饰引用变量时,仅表示这个引用变量类型是不可被重新赋值的,但引用类型变量所指向的实例依然可以改变。若不可变类中包含的成员变量是引用变量,那么

    这个引用变量的对象是可变的,则这个不可变类是失败的不可变类:

 1 //这是一个可变类,因为Person类中的name引用的对象是可以更改的
 2 class Name{
 3     private String firstName;
 4     private String lastName;
 5     public Name(){}
 6     public Name(String firstName, String lastName){
 7         this.firstName = firstName;
 8         this.lastName = lastName;
 9     }
10     
11     public String getFirstName(){
12         return firstName;
13     }
14     public void setFirstName(String firstName){
15         this.firstName = firstName;
16     }
17     public String getLastName(){
18         return lastName;
19     }
20     public void setLastName(String lastName){
21         this.lastName = lastName;
22     }
23 }
24 
25 public class Person{
26     private final Name name;
27     public Person(Name name){
28         this.name = name;
29     }
30     public Name getName(){
31         return name;
32     }
33     public static void main(String[] args){
34         Name n = new Name("悟空", "孙");
35         Person p = new Person(n);
36         //Person对象的name得firstName值为“悟空”
37         System.out.println(p.getName().getFirstName());
38         //改变Person对象的name的firstName值
39         n.setFirstName("八戒");
40         //Person对象的name的firstName值被改为“八戒”
41         System.out.println(p.getName().getFirstName());
42     }
43 }
View Code

    将上面的可变类改为不可变类:

 1 //这是一个可变类,因为Person类中的name引用的对象是可以更改的
 2 class Name{
 3     private String firstName;
 4     private String lastName;
 5     public Name(){}
 6     public Name(String firstName, String lastName){
 7         this.firstName = firstName;
 8         this.lastName = lastName;
 9     }
10     
11     public String getFirstName(){
12         return firstName;
13     }
14     public void setFirstName(String firstName){
15         this.firstName = firstName;
16     }
17     public String getLastName(){
18         return lastName;
19     }
20     public void setLastName(String lastName){
21         this.lastName = lastName;
22     }
23 }
24 
25 public class Person{
26     private final Name name;
27     public Person(Name name){
28         //设置name实例变量为临时创建的Name对象,该对象的firstName和lastName
29         //与传入的name参数的firstName和lastname相同
30         this.name = new Name(name.getFirstName(), name.getLastName());
31     }
32     public Name getName(){
33         //返回一个匿名对象,该对象的firstName和lastName
34         //与该对象里的name的firstName和lastName相同
35         return new Name(name.getFirstName(), name.getLastName());
36     }
37     public static void main(String[] args){
38         Name n = new Name("悟空", "孙");
39         Person p = new Person(n);
40         //Person对象的name得firstName值为“悟空”
41         System.out.println(p.getName().getFirstName());
42         //改变Person对象的name的firstName值
43         n.setFirstName("八戒");
44         //Person对象的name的firstName值被改为“八戒”
45         System.out.println(p.getName().getFirstName());
46     }
47 }
View Code

    上面的Person类就是一个不可变类,即使再怎么更改n.setFirstName()和n.setLastName(),也不会改变Person类中name引用的对象的值。

  缓存实例的不可变类:

 1 class CacheImmutale{
 2     private static int MAX_SIZE = 10;
 3     //使用数组来缓存已有的实例
 4     private static CacheImmutale[] cache = new CacheImmutale[MAX_SIZE];
 5     //记录缓存实例在缓存中的位置,cache[pos - 1]是最新缓存的实例
 6     private static int pos = 0;
 7     private final String name;
 8     private CacheImmutale(String name){
 9         this.name = name;
10     }
11     public String getName(){
12         return name;
13     }
14     public static CacheImmutale valueOf(String name){
15         //遍历已缓存的对象
16         for(int i = 0; i < MAX_SIZE; i++){
17             //如果已有相同实例,则直接返回该缓存的实例
18             if(cache[i] != null && cache[i].getName().equals(name)){
19                 return cache[i];
20             }
21         }
22         //若缓存池已满
23         if(pos == MAX_SIZE){
24             //把缓存的第一个对象覆盖,即把刚刚生成的对象放在缓存池的最开始位置
25             cache[0] = new CacheImmutale(name);
26             //把pos设为1
27             pos = 1;
28         }else{
29             //把新创建的对象缓存起来,pos加1
30             cache[pos++] = new CacheImmutale(name);
31         }
32         return cache[pos - 1];
33     }
34     public boolean equals(Object obj){
35         if(this == obj){
36             return true;
37         }
38         if(obj != null && obj.getClass() == CacheImmutale.class){
39             CacheImmutale ci = (CacheImmutale) obj;
40             return name.equals(ci.getName());
41         }
42         return false;
43     }
44     public int hashCode(){
45         return name.hashCode();
46     }
47 }
48 
49 public class CacheImmutaleTest{
50     public static void main(String[] args){
以上是关于第六章.面向对象(下)的主要内容,如果未能解决你的问题,请参考以下文章

第六章-面向对象的程序设计—创建对象

第六章 Python类(面向对象编程)

第六章

Python开发第六章:Python面向对象

第六章-面向对象编程

JAVA-初步认识-第六章-面向对象