第6章 面向对象(下)

来源:互联网 发布:金融管理信息系统软件 编辑:程序博客网 时间:2024/06/05 07:53
一、Java 8 增强的包装类
基本数据类型的介绍(p49)

  1. 为了解决8中接本数据类型的变量不能被当成Object类型变量使用的问题,Java提供了包装类的概念。
自动装箱:把一个基本类型变量直接赋给对应的包装类变量,Integer inObj = 5;(直接把基本类型变量赋给了Integer包装类)
自动拆箱:直接把包装类对象赋给一个对应的基本类型变量,int i = inObj;

  1. 基本类型变量和字符串之间的转换
(1)包装类提供的parseXxx(String s)静态方法(出了Character之外的所有包装类)
(2)包装类提供的Xxx(String s)构造方法
(3)基本类型数据 转换成 字符串:String类提供的多个重载的valueOf()方法   
publicclass StringTrans {
       publicstatic void main(String[] args) {
              //TODO Auto-generated method stub
              String s="123";
              
              //使用包装类提供的静态方法parseXxx(String s)和构造器Xxx(String s):将字符串类型转换成基本数据类型变量
              inti1=Integer.parseInt(s);
              inti2=newInteger(s);
              System.out.println(i1+i2);
              
              //使用String类提供的多个重载方法valueOf():将基本数据类型转换成字符串
              String s1 = String.valueOf(2.345f);
              System.out.println(s1);
              
              //直接在基本类型变量后加上“”运算符,系统自动把基本类型变量转换成字符串
              String s2 = 5+"";
              System.out.println(s2);
       }
}
输出:
246
2.345
5

  1. 两个包装类的比较
Java 7为包装类提供了一个静态方法:compare(xxx val1, xxx val2),来较两个基本类型值的大小
//Java 7 为包装类提供了一个静态方法compare(xxx,xxx)来比较两个基本类型值的大小
System.out.println(Boolean.compare(true,false));
System.out.println(Float.compare(2.25f, 2.23f));

Java 8  增加的功能:
(1)为整形包装类增加了支持无符号运算的方法
(2)为Byte、Short增加了toUnsignedInt(xxx x)、toUnsignedLong(xxx x)两个方法,将指定byte或short类型的变量会值转换成无符号int或long值.



二、处理对象
  1. Object类提供的toString()方法:总是返回该对象实现类的“类名+@+hashCode值”
自定义的类可以重写Object类的toString()方法,以实现打印自我描述信息的功能。
// 重写toString方法,用于实现Apple对象的"自我描述"
publicString toString()
{
     return"Apple[color="+color+", weight="+weight+"]";
}

Apple a =new Apple("红色", 5.68);
// 打印Apple对象
System.out.println(a.toString());  //等价于System.out.println(a);  
输出:Apple[color=红色, weight=5.68]

  1. ==和equals方法
(1)==
对于基本类型变量,且都是数值类型(数据类型不一定相同):只要两个变量的值相等,就返回true
对于引用类型变量:只有它们指向同一个对象时,==才会返回true。(不能用于比较类型上没有父子关系的两个对象)
publicclass EqualTest
{
       publicstatic void main(String[] args)
       {
              intit = 65;   
              floatfl = 65.0f;
              // 将输出true
              System.out.println("65和65.0f是否相等?"+ (it == fl));
              charch = 'A';
              // 将输出true
              System.out.println("65和'A'是否相等?"+ (it == ch));
              String str1 =new String("hello");
              String str2 =new String("hello");
              // 将输出false
              System.out.println("str1和str2是否相等?"
                     + (str1 == str2));
              // 将输出true
              System.out.println("str1是否equals str2?"
                     + (str1.equals(str2)));
              // 由于java.lang.String与EqualTest类没有继承关系,
              // 所以下面语句导致编译错误
//            System.out.println("hello" == new EqualTest());
       }
}

  • “hello”直接量:JVM将形如“hello”的字符串直接量(包括编译时就可以计算出来的字符串值),使用常量池来管理这些字符串。
  • 而new String("hello"):JVM先使用常量池来管理“hello”直接量,再调用String类的构造器来创建一个新的String对象,新创建的String对象被保存在堆内存中。即new String("hello")姨公产生了两个字符串对象

(2)equals()方法
String对象的equals()方法:只要两个String对象里包含的字符序列相同就认为相等
Object类的equals()方法:只有引用变量指向同一个对象才返回true。(判断两个对象相等的标准与==运算符没有区别)
publicclass StringCompareTest
{
       publicstatic void main(String[] args)
       {
              // s1直接引用常量池中的"疯狂Java"
              String s1 ="疯狂Java";
              String s2 ="疯狂";
              String s3 ="Java";
              // s4后面的字符串值可以在编译时就确定下来
              // s4直接引用常量池中的"疯狂Java"
              String s4 ="疯狂" + "Java";
              // s5后面的字符串值可以在编译时就确定下来
              // s5直接引用常量池中的"疯狂Java"
              String s5 ="疯" + "狂" + "Java";
              // s6后面的字符串值不能在编译时就确定下来,
              // 不能引用常量池中的字符串
              String s6 = s2 + s3;
              // 使用new调用构造器将会创建一个新的String对象,
              // s7引用堆内存中新创建的String对象
              String s7 =newString("疯狂Java");
              System.out.println(s1 == s4);// 输出true
              System.out.println(s1 == s5);// 输出true
              System.out.println(s1 == s6);// 输出false
              System.out.println(s1 == s7);// 输出false
       }
}

实际应用中,常常要重写equals()方法,相等条件由业务要求决定。
classPerson
{
       privateString name;
       privateString idStr;
       publicPerson(){}
       publicPerson(String name , String idStr)
       {
              this.name = name;
              this.idStr = idStr;
       }
       // 此处省略name和idStr的setter和getter方法。
       // name的setter和getter方法
       publicvoid setName(String name)
       {
              this.name = name;
       }
       publicString getName()
       {
              returnthis.name;
       }
       // idStr的setter和getter方法
       publicvoid setIdStr(String idStr)
       {
              this.idStr = idStr;
       }
       publicString getIdStr()
       {
              returnthis.idStr;
       }
       // 重写equals()方法,提供自定义的相等标准
       publicboolean equals(Object obj)
       {
              // 如果两个对象为同一个对象
              if(this== obj)
                     returntrue;
              // 只有当obj是Person对象
              if(obj != null && obj.getClass() == Person.class)
              {
                     Person personObj = (Person)obj;
                     // 并且当前对象的idStr与obj对象的idStr相等才可判断两个对象相等
                     if(this.getIdStr().equals(personObj.getIdStr()))
                     {
                           returntrue;
                     }
              }
              returnfalse;
       }
}
publicclass OverrideEqualsRight
{
       publicstatic void main(String[] args)
       {
              Person p1 =new Person("孙悟空", "12343433433");
              Person p2 =new Person("孙行者", "12343433433");
              Person p3 =new Person("孙悟饭", "99933433");
              // p1和p2的idStr相等,所以输出true
              System.out.println("p1和p2是否相等?"
                     +p1.equals(p2));
              // p2和p3的idStr不相等,所以输出false
              System.out.println("p2和p3是否相等?"
                     +p2.equals(p3));
       }
}



三、类成员
什么是类成员?
static关键字修饰的成员就是 类成员类变量、类方法、静态初始化块
static不能修饰构造器,static修饰的类成员属于整个类,不属于单个实例。

static关键字非常重要的规则:类成员不能访问实例成员!!

四、final修饰符
final关键字:修饰类、变量和方法,用它修饰的类、方法、变量是不可以改变的!

(1)final修饰成员变量:
类变量:必须在静态初始化块、或声明该类变量时 指定初始值,而且只能在两个地方之一指定。
实例变量:必须在普通初始化快、或声明该实例变量、或构造器中指定初始值。
  • 不用final修饰的成员变量:先不用显式指定初始值,因为系统会默认分配初始值“0、false、null、'\u0000' ”
  • 系统不会对final成员变量进行默认初始化,因此不能再初始化之前就访问成员变量。

(2)final修饰局部变量:
系统不会对局部变量进行初始化,局部变量必须由程序员显式初始化。
使用final修饰的局部变量,既可以在定义是指定默认值,也可以在后面代码中对该final变量赋初始值。但只能一次,不能重复赋值!

(3)final修饰基本类型变量和引用类型变量的区别:
final修饰基本类型变量时,不能对基本类型变量重新赋值,基本类型变量不能被改变!
final修饰引用类型变量时,由于引用类型变量只是保存它所引用的地址,即这个地址不可被改变!但是这个地址指向的实际对象的内容时可以变的!

(4)可执行“宏替换”的final变量

(5)final方法:
final修饰的方法不可以被重写(否则编译出错),但可以被重载!
若不希望子类重写父类的某个方法,则可以使用final修饰该方法!

private修饰的方法不可以被子类访问,所以子类无法重写该方法。但可以在子类中定义一个与该方法方法名、形参列表、返回值都相同的方法,这不是重写,而是重新定义了一个新的方法。
所以,使用private final修饰的方法可以在子类中包含同名同参的新方法。

(6)final类:
final修饰的类不可以有子类!(否则编译出错)


五、不可变类
  1. 不可变类(immutable)类:创建该类的实例后,该实例的实例变量不可改变。
Java的8个包装类和java.lang.String都是不可变类。

  1. 遵循的规则:
(1)使用private和final修饰该类的成员变量:不可在类外访问,不可改变
(2)提供带参构造器:根据传入的参数来初始化类里的成员变量
(3)仅为该类的成员变量提供getter方法,不提供setter方法
(4)若有必要,重写Object类的hashCode()和equals()方法

  1. 当不可变类包含引用类型的成员变量,且这个引用类是可变类时,会导致该不可变类变成可变类!
如何避免呢?
创建一个与可变类完全相同的另一个对象,传入该不可变类,则当可变类改变时,另一个对象是不会改变的,不可变类也将不被改变。
...缓存池??















原创粉丝点击