第六章.面向对象(下)
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 }
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 }
把基本类型转换为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 }
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 }
这里判断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 }
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 }
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 }
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 }
将上面的可变类改为不可变类:
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 }
上面的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){ 以上是关于第六章.面向对象(下)的主要内容,如果未能解决你的问题,请参考以下文章