Java面向对象 ( 中 )
观看b站尚硅谷视频做的笔记
1、 面向对象特征之二:继承性 (inheritance)
有一个Person类
发现Student类也有Person类这些属性,多了一个属性
测试类
目前Pesron类和Student类没有任何关系
但是Pesron类和Student类都有一些共同
既然Pesron类已经定义过了,Student类先定义的类,能不能复用一下定义已经定义好的结构
如何实现定义一个Student,不用去写一行一行代码?
继承extends
扩展:类与类之间都有哪些关系
继承性的好处(why为什么要有继承性)
提高的代码的复用性(谁想调就调)
多态性的前提就是需要有继承
体现:一旦子类 A 继承父类 B 以后,子类 A 就获取了父类 B 中声明的所有属性和方法。构造器本身是造对象使用的,不能说是对象去调构造器,构造器后面关键字super再讲,此处主要体现属性或方法,一旦继承后,就获取了父类的属性方法。
获取:当造对象时,通过子类对象去调属性或方法。
封装性解决的是可见性的问题
继承性解决的是能不能拿到里面结构的问题
继承性说都能拿到,能不能调还需要看封装性
Java 中关于继承性的规定:
一个父类可以有多个子类,一个类可以被多个子类继承
一个类只能有一个父类称为单继承,后续会讲接口,类是可以实现多个接口(也可以通过这样实现扩展功能)
2、方法的重写 (ocerride / overwrite)
3、关键字:super
super理解为:父类的。
super可以用来调用:属性、方法、构造器。
super的使用
我们可以在子类的方法或构造器中,通过super.属性或super.方法方式,显式的调用父类中声明的属性或方法,但是,通常情况下,习惯省略super.
特殊情况下:当子类和父类中定义了父类中定义了同名的属性,则必须显示的使用使用super.属性的方式,表面调用的是父类中声明的属性。
特殊情况:当子类重写父类中的方法,想在子类的方法中调用父类中被重写的方法,必须显示的使用super.方式表明调用的是父类中被重写的方法。
super调用构造器:在子类的构造器中显示的使用super(形参列表)的方式,调用父类中声明的指定构造器。
super(形参列表)的使用,必须声明在子类构造器的首行。
在类的构造器中,针对于this形参列表或super只能二选一,不能同时出现。
在构造器的首行,既没有显示的声明this(形参列表)或super形参列表,则默认的是调用父类中的空参构造器。super()
在类的多个构造器中,至少有一个类的构造器使用了super(形参列表)调用父类中的构造器。
重写了父类中的方法,
this关键字是属性、与形参同名,避免同名。
super关键字子父类,子类重写父类中被重写的方法,覆盖了父类中的被重写的方法,在子类中想要再调用父类中的被重写的方法,想要进行区分。
super关键字的使用
Person 类
public Person(String name,int age){
this(name);构造器
this.age = age;
}
Student 类
测试类
super理解为父类,所以主要在Student子类中如何调父类中的结构
public void show(){
system.out.println(“name=”+this.name+“.age=”+super.age);
}
this.name当前对象的堆空间中找name结构
什么时候用super?
Person类中定义了int id;学生类中也定义了一个int id;子父类中出现同名的属性,内存中有两个属性id
super调用构造器
4、子类对象实例化过程
Dog类的直接父类是animal
子类对象实例化过程
1.在结果上看:子类继承父类以后,就获取了父类中声明的属性或方法。
创建子类的对象中,在堆空间中,就会加载所有父类中声明的属性。
2.从过程上看:当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用父类构造器,直到调用了java.lang.Object类中空参的构造器为止。正因为加载所有的父类结构。
一个类有N个构造器,最多有n-1个this,没写那个一定是super,new dog对象会直接间接的调用animal构造器,animal会直接间接调用Creature构造器,这是为啥?
new了一dog对象,为啥有了anima的属性?
在创建子类对象时,直接间接调用了父类构造器
5、 面向对象特征之三:多态性
person类
Man 类
Woman 类
测试类
-
理解多态性:可以理解为一个事物的多种态性。
-
对象的多态性,父类的引用指向子类的对象(或子类的对象赋值给父类的引用)
-
多态的使用:虚拟方法调用
-
有了对象多态性以后,在编译器,只能调用父类声明的方法,但在执行实际执行的是子类重写父类的方法。简称,编译时,看左边,运行时看右边。若 编 译 时 类 型 和 运 行 时 类 型 不 一 致, 就 出 现 了 对 象 的 多 态 性
(Polymorphism)。
多态情况下:
看左边:看的是父类的引用(父类中不具备子类特有的方法)
看右边:看的是子类的对象(实际运行的是子类重写父类的方法) -
多态性的使用前提:
① 类的继承关系;
② 方法的重写。 -
对象的多态性:只适用于方法,不适用于属性 ( 编译和运行都看左边 )
Person p2 = new Man();
p2.eat();
p2.walk();
编译时看左边的类型,执行时子类重写的方法
父类的引用 p2
子类的对象new Man();
调子类方法不能调,p2.earnMoney();
.出来的是Person类的
package com.zhou.java;
public class PersonTest {
public static void main(String[] args) {
Person person = new Person();
person.eat();
Man man = new Man();
man.eat();
man.age = 25;
System.out.println(man.age);
man.earnMoney();
System.out.println("************************************");
//对象的多态性:父类的引用指向子类的对象
Person p = new Man();
Person p1 = new Woman();
//多态的使用:当调用子父类同名参数方法时,实际调用的是子类重写父类的方法--虚拟方法调用
// .出来的是Person类的
p.eat();
p1.eat();
//子类方法不能调
p1.earnMoney();
}
}
class Person {
String name;
int age;
public void eat() {
System.out.println(" 人,吃饭 ");
}
public void walk() {
System.out.println(" 人,走路 ");
}
}
class Woman extends Person {
boolean isBeauty;
public void goShopping() {
System.out.println("女人喜欢购物");
}
public void eat() {
System.out.println(" 女人少吃,为了减肥 ");
}
public void walk() {
System.out.println(" 女人,窈窕的走路 ");
}
}
class Man extends Person {
boolean isSmoking;
public void earnMoney() {
System.out.println("男人负责工作养家");
}
public void eat() {
System.out.println(" 男人多吃,长肌肉 ");
}
public void walk() {
System.out.println(" 男人霸气走路 ");
}
}
为什么要有多态性?为什么要用多态性?
举例一
public class AnimalTest {
public static void main(String[] args) {
AnimalTest test = new AnimalTest();
test.func(new Dog());此处要传一个实例
test.func(new Cat());
}
public void func(Animal animal){//Animal animal = new Dog();
animal.eat();因为声明的是Animal类型,只能调Animal的方法,执行的时候子类重写后的方法
animal.shout();
}
package com.zhou.java;
public class AnimalTest {
public static void main(String[] args) {
AnimalTest animalTest = new AnimalTest();
animalTest.fun(new Dog());
animalTest.fun(new Cat());
}
public void fun(Animal animal) {//Animal animal=(new Dog()
animal.eat();
animal.shout();
}
// 如果没有多态性,就会写很多如下的方法,去调用
public void func(Dog dog) {
dog.eat();
dog.shout();
}
public void func(Cat cat) {
cat.eat();
cat.shout();
}
}
class Animal {
public void eat() {
System.out.println(" 动物,进食 ");
}
public void shout() {
System.out.println(" 动物:叫 ");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("狗吃骨头");
}
public void shout() {
System.out.println("汪汪汪");
}
}
class Cat extends Animal {
public void eat() {
System.out.println(" 猫吃鱼 ");
}
public void shout() {
System.out.println(" 喵!喵!喵! ");
}
}
举例二
class Order{
public void method(Object obj){传任何一个对象都可以
}
}
举例三
对象的多态性:只适用于方法,不适用于属性 ( 编译和运行都看左边 )
package com.zhou.java;
public class PersonTest1 {
public static void main(String[] args) {
Person1 person1 = new Man1();
System.out.println(person1.age);
}
}
class Person1 {
String name;
int age = 1001;
public void eat() {
System.out.println("人,吃饭");
}
public void walk() {
System.out.println("人,走");
}
}
class Man1 extends Person1 {
boolean isSmoking;
int id = 1002;
}
5.1、 虚拟方法的补充
从编译和运行的角度看:
重载,是指允许存在多个同名方法,而这些方法的参数不同。
。
编译器根据方法不同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。它们的调用地址在编译期就绑定了。Java 的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;而对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为“晚绑定”或“动态绑定”。
引用一句 Bruce Eckel 的话:“不要犯傻,如果它不是晚绑定,它就不是多态。”
5.2、向下转型的使用
// 如何才能调用子类所特有的属性和方法?
对编译器来讲,声明的p2不再是Person类型就行
赋值左边右边要么类型需要一样,要么像基本数据类型中自动提升,子类对象可以赋给父类,
基本数据类型int–double,直接转,称为自动类型提升
基本数据类型double-int,使用强制类型转换,用()里面放需要转换的类型(double)
Man m1 = (Man) p2;
m1.earnMoney();
m1.isSmoking = true;
在内存中的结构?
一开始栈中声明了p2,堆空间这new了一个man对象,man对象中有person父类的对象中的属性与方法,也有man中的属性与方法,man对象中的地址值赋给p2,地址值有两个部分:前面是类型,后面是@地址,因为地址值有类型的限制,直接赋值给m1时,就不让赋值,使用(man)强转,就可以了,将地址完全就赋值过来给m1,即m1指向man对象,编译器认为此时是Man类型,即就可以去调man对象中的属性与方法
// 使用强转时,可能出现 ClassCastException 异常
Woman w1 = (Woman)p2;因为此时的p2是man
为了避免这种方式的出现?使用instanceof
任何一个类的对象可以作为Object类的实例
// 向下转型的常见问题
// 问题二 : 编译通过,运行时也通过,这是可以的
Object obj = new Woman();
Person p = (Person)obj;
woman赋给obj,向上转型(多态性),再将obj强转成person
编译通过,运行不通过
Person p4 = new Person();
Man m4 = (Man)p4;
Object o = new Date();
// String str1 = (String)o;
```java
package com.zhou.java;
public class PersonTest2 {
public static void main(String[] args) {
Person2 p2 = new Man2();
// p2.earnMoney();
// 不能调用子类所特有的方法、属性,编译时,p2 是 Person类型
//有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法,
// 但是由于变量声明为父类类型,导致编译时,只能调用父类中的属性和方法。子类的属性和方法不能调用
// 如何才能调用子类所特有的属性和方法?对编译器来讲,声明的p2不再是Person类型就行
// 赋值左边右边要么类型需要一样,要么像基本数据类型中自动提升,子类对象可以赋给父类
//使用强转,也可称向下转型:
Man2 m2 = (Man2) p2;
m2.earnMoney();
m2.isSmoking = true;
// 使用强转时,可能出现 ClassCastException 异常
// Woman2 w2=(Woman2) p2;
// w2.goShopping();
// 为了避免这种异常ClassCastException 异常出现?使用instanceof
// a instanceof A:判断对象a是否是类A的实例,如果是,返回true,如果不是,返回false
/* 使用情境:为了避免在向下转型时出现 ClassCastException
异常,我们在进行向下转型之前,先进行 instanceof 的判断 , 一旦返回
true, 就进行向下转型。如果返回 false,不进行向下转型。
如果a instanceof A返回true,则a instanceof B也返回true,其中类B是类A的父类。
*/
if(p2 instanceof Woman2){
Woman2 w3=(Woman2)p2;
w3.goShopping();
System.out.println("**********Woman*********");
}
if (p2 instanceof Man2){
Man2 m3= (Man2) p2;
m3.earnMoney();
System.out.println("**********Man*********");
}
if (p2 instanceof Person2){
Person2 p3= (Person2) p2;
System.out.println("**********Person*********");
}
if (p2 instanceof Object){
System.out.println("**********Object*********");
}
//向下转型的常见问题:
//问题1 :编译通过,运行不通过
// Person2 p4= new Woman2();
// Man2 m4=(Man2) p4;
// Person2 p5= new Person2();
// Man2 m5=(Man2) p5;
//问题2 :编译通过,运行通过
Object obj= new Woman2();
Person2 p5=(Person2) obj;
//问题3 :编译不通过,运行不通过
// Man2 m6 = new woman2();
// String str = new Date();
// Object o = new Date();
// String str1 = (String)o;
}
}
class Person2 {
String name;
int age;
public void eat() {
System.out.println(" 人,吃饭 ");
}
public void walk() {
System.out.println(" 人,走路 ");
}
}
class Woman2 extends Person2 {
boolean isBeauty;
public void goShopping() {
System.out.println(" 女人喜欢购物 ");
}
public void eat() {
System.out.println(" 女人少吃,为了减肥。");
}
public void walk() {
System.out.println(" 女人,窈窕的走路。");
}
}
class Man2 extends Person2 {
boolean isSmoking;
public void earnMoney() {
System.out.println(" 男人负责工作养家 ");
}
public void eat() {
System.out.println(" 男人多吃肉,长肌肉 ");
}
public void walk() {
System.out.println(" 男人霸气的走路 ");
}
}
引用数据类型的==,
System.out.println(b == s); //true比较的是两个引用数据类型变量的地址值是否相同。
System.out.println(b.count); //10,多态性不适用于属性
b.display();20
- 若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中。编译看左边,运行看右边
-
- 对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量。编译运行都看左边
- package com.zhou.java;
public class MethodTest {
public static void main(String[] args) {
Sub sub = new Sub();
System.out.println(sub.count);
sub.display();
Base b= sub;
System.out.println(b==sub);
System.out.println(b.count);
b.display();
}
}
class Base{
int count= 10;
public void display() {
System.out.println(this.count);
}
}
class Sub extends Base{
int count= 20;
public void display() {
System.out.println(this.count);
}
}
``
6、Object 类的使用
6.1 、Object 类中的主要结构
java.lang.Object类
1)Objetc类是所有Java类中的根父类
2)如果在类的声明中未使用extends关键字指明其父类,则默认父类java.lang.Object类
3)Object类中的功能(属性、方法)就具有通用性
属性:无
方法:equals()、toString()、getClass()、hashCode() clone() / finalize() / wait() / notify() / notifyAll()。
xxx.getClass().getSuperClass()获取xxx是谁造的,然后再获取它的父类。
Object定义在lang包下
4)Object只声明了一个空参构造器,造的所有对象都会调用到Object类的空参构造器
finalize方法:
若对象在栈中没有任何引用指向,就会调用finalize方法,将堆空间中的实体进行回收
通常情况都不会主动调用此方法,垃圾收集器自动调。
6.2 、== 操作符与 equals 方法
一、= =运算符:
1)可以使用在基本数据类型和引用数据类型变量当中
2)如果比较的是基本数据类型变量,比较两个变量保存的数据是否相等。(不一定类型要相同)
如果比较的是引用数据类型变量,比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体。补充==符号使用时,必须保证符合左边两边的变量类型一致
测试
二、equals() 方法的使用
1.)是一个方法,而运算符
2)只能适用于引用数据类型
3)Object类中equals()方法的定义
public boolean equals(Object obj){
return (this == obj);
}
说明:Object类中定义的equals()方法和= =作用是相同的,比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体。
4)像String、Date、File、包装类等都重写了Object类中的equals()方法,两个引用的地址是否相同,而是比较两个对象的实体内容是否相同。
5)通常情况下,我们自定义的类如果使用equals()的话,也通常时比较两个对象的实体内容是否相同,那么,我们就需要对Object类中的equals()进行重写。
重写的原则:比较两个对象的实体内容是否相同。
package com.zhou.java;
import java.util.Date;
public class EqualsTest {
public static void main(String[] args) {
int i = 10;
int j = 10;
double d = 10.0;
boolean a = true;
System.out.println(i == j);
System.out.println(j == i);
// System.out.println(a==j);
char c = 10;
System.out.println(i == c);
char c1 = 'A';
char c2 = 65;
System.out.println(c1 == c2);
//引用数据类型
Customer cust1 = new Customer("Tom", 21);
Customer cust2 = new Customer("Tom", 21);
System.out.println(cust1 == cust2);
String str1 = new String("BAT");
String str2 = new String("BAT");
System.out.println(str1 == str2);
System.out.println(cust1.equals(cust2));
System.out.println(str1.equals(str2));
Date date1 = new Date(23432525324L);
Date date2 = new Date(23432525324L);
System.out.println(date1 == date2);
System.out.println(date1.equals(date2));
}
}
class Customer {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Customer() {
super();
}
public Customer(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Customer) {
Customer cust = (Customer) obj;
//比较两个对象的属性是否相同
if (this.age == cust.age && this.name.equals(cust.name)) {
return true;
} else {
return false;
}
}
return false;
}
}
6.3、 重写 equals() 方法的原则
对称性:如果 x.equals(y) 返回是“true”,那么 y.equals(x) 也应该返回
是“true”。
自反性:x.equals(x) 必须返回是“true”。
传递性:如果 x.equals(y) 返回是“true”,而且 y.equals(z) 返回是“true”,
那么 z.equals(x) 也应该返回是“true”。
一致性:如果 x.equals(y) 返回是“true”,只要 x 和 y 内容一直不变,
不管你重复 x.equals(y) 多少次,返回都是“true”。
任何情况下,x.equals(null),永远返回是“false”;x.equals( 和 x 不同类
型的对象 ) 永远返回是“false”。
6.4、 toString 的使用
Object类中toString()的使用
1)当我们输出一个引用对象时,实际就是调用当前对象的toString方法
2)Object类中的toSring的定义方法
public String toString(){
return getClass.getName()+“@”+Integer.toHexString(hashCode())
}
3)像String、Date、File、包装类都重写了Objetc类中的toString()方法。使得在调用toString()时,返回实体内容信息。
4)自定义类如果重写toString()方法,当调用此方法时,返回对象的实体内容。
public class ToStringTest {
String str = new String(“MM”);
System.out.println(str);为啥这里出来不是地址值,就只有String重写过
自定义类重写toString()
想看对象的信息,就直接重写toString方法
package com.zhou.java;
import java.util.Date;
public class EqualsTest {
public static void main(String[] args) {
int i = 10;
int j = 10;
double d = 10.0;
boolean a = true;
System.out.println(i == j);
System.out.println(j == i);
// System.out.println(a==j);
char c = 10;
System.out.println(i == c);
char c1 = 'A';
char c2 = 65;
System.out.println(c1 == c2);
//引用数据类型
Customer cust1 = new Customer("Tom", 21);
Customer cust2 = new Customer("Tom", 21);
System.out.println(cust1 == cust2);
String str1 = new String("BAT");
String str2 = new String("BAT");
System.out.println(str1 == str2);
System.out.println(cust1.equals(cust2));
System.out.println(str1.equals(str2));
Date date1 = new Date(23432525324L);
Date date2 = new Date(23432525324L);
System.out.println(date1 == date2);
System.out.println(date1.equals(date2));
}
}
class Customer {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Customer() {
super();
}
public Customer(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Customer) {
Customer cust = (Customer) obj;
//比较两个对象的属性是否相同
if (this.age == cust.age && this.name.equals(cust.name)) {
return true;
} else {
return false;
}
}
return false;
}
@Override
public String toString() {
return "Customer\"[\"name=\"+name+\",age=\"+age]";
}
}
package com.zhou.java;
public class ToStringTest {
public static void main(String[] args) {
Customer cust1 = new Customer("Tom",21);
System.out.println(cust1);
System.out.println(cust1.toString());
String str = new String("MM");
System.out.println(str);
}
}
7、包装类 (Wrapper) 的使用
7.1 、单元测试方法的使用
java中JUnit单元测试
步骤 :
- 选中当前项目工程 --》 右键:build path --》 add libraries --》
JUnit 4 --》 下一步; - 创建一个 Java 类进行单元测试。
此时的 Java 类要求:①此类是公共的 ②此类提供一个公共的无参构造器 - 此类中声明单元测试方法。
此时的单元测试方法:方法的权限是 public, 没有返回值,没有形参。 - 此单元测试方法上需要声明注解:@Test 并在单元测试类中调用:
import org.junit.Test; - 声明好单元测试方法以后,就可以在方法体内测试代码。
- 写好代码后,左键双击单元测试方法名:右键 --》 run as --》
JUnit Test;
说明:如果执行结果无错误,则显示是一个绿色进度条,反之,错误
即为红色进度条。
原来讲的:定义了一个成员变量,在main方法中调用,需要在main方法中创一个对象,通过对象.属性去调用
现在直接可以调用
package com.zhou.java;
import org.junit.Test;
public class JunitTest {
@Test
public void testEquals(){
int num=10;
String s1="MM";
String s2="MM";
System.out.println(s1.equals(s2));
System.out.println(num);
//ClassCastException 的异常
/*Object obj = new String("GG");
Date date=(Date)obj;*/
}
}
7.2、 包装类的使用
java提供了8种基本数据类型对应的包装类,使得本数据类型的变量具有类的特征
注意:其中Byte,Short,Integer、Long、Float、Double的父类是:Number
7.3、包装类与基本数据类型相互转换
基本数据类型与包装类如何转换?
字符串转换为基本数据类型?
1) 基本数据类型 --》包装类 , 调用包装类的构造器(应用场景:有方法的形参是Object类型,就必须把基本数据类型转换成包装类,形参才能用)
@Test
public void test1() {
Integer in1 = new Integer(num1);
此时in1就是把10包装起来的包装类
package com.zhou.java;
import org.junit.Test;
public class WrapperTest {
//基本数据类型--包装类,调用包装类的构造器
@Test
public void test1() {
int num = 10;
Integer in1 = new Integer(num);
System.out.println(in1.toString());
Integer in2 = new Integer("123");
System.out.println(in2.toString());
// 报异常
// 报异常
/*Integer in3 = new Integer("123abc");
System.out.println(in3.toString());*/
Float f1 = new Float(12.3f);
Float f2 = new Float("12.3");
System.out.println(f1);
System.out.println(f2);
Boolean b1 = new Boolean(true);
System.out.println(b1);
Boolean b2 = new Boolean("true");
System.out.println(b2);
Boolean b3 = new Boolean("true123");
System.out.println(b3);
Order order = new Order();
System.out.println(order.isMale);
System.out.println(order.isFemale);
}
}
class Order {
boolean isMale;
Boolean isFemale;
}
2)包装类 --》 基本数据类型 : 调用包装类的 xxxValue()
package com.zhou.java;
import org.junit.Test;
public class WrapperTest {
// 包装类 --》 基本数据类型:调用包装类的xxxValue()
@Test
public void Test2(){
Integer in1 = new Integer(12);
int i = in1.intValue();
System.out.println(i+1);
Float f1 = new Float(12.3f);
float v = f1.floatValue();
System.out.println(v+1);
}
}
3)JDK 5.0 新特性 : 自动装箱与自动拆箱
public void method(Object obj){
System.out.println(obj);
}
真正调method这个方法的时候,可以传Objetc类型的子类对象,
但是现在这会儿将num1放进去也没事儿
正常来讲num1是不能放到method里的
怎么解释这个? Object obj = num1
这里并不是//将int num1赋给Object obj ,这是错误的
这里是因为自动装箱,自动拆箱
// 自动装箱 :就可以替代包装类 , 调用包装类的构造器,就用不着我们去new了
package com.zhou.java;
import org.junit.Test;
public class WrapperTest {
//JDK 5.0 新特性 : 自动装箱与自动拆箱
@Test
public void Test3() {
// int num1=10;
// method(num1);
// 以前真正调method这个方法的时候,
// 可以传Objetc类型的子类对象,正常来讲num1是不能放到method里的,
// 但是现在这会儿将num1放进去也没事儿
/* 怎么解释: Object obj = num1
这里并不是//将int num1赋给Object obj ,这是错误的
这里是因为自动装箱,自动拆箱
自动装箱 :就可以替代包装类 , 调用包装类的构造器,就用不着去new了*/
//自动装箱:基本数据类型--》包装类
int num2=10;
Integer in1=num2;//自动装箱
boolean b1=true;
boolean b2=b1;//自动装箱
//自动拆箱:包装类--》基本数据类型
System.out.println(in1);
int num3= in1;
}
public void method(Object obj){
System.out.println(obj);
}
}
4)基 本 数 据 类 型、 包 装 类 —》String 类 型, 调 用 String 重 载 的valueOf(Xxx xxx)
package com.zhou.java;
import org.junit.Test;
/*基 本 数 据 类 型、 包 装 类 ---》String 类 型,
调 用 String 重 载 的valueOf(Xxx xxx)*/
public class WrapperTest {
@Test
public void test4(){
int num1=10;
//方式一:连接运算
String str1=num1+" ";
System.out.println(str1);
//方式二:调用Sting的valuseOf()
float f1=12.3f;
String s = String.valueOf(f1);
System.out.println(s);
Double d1=new Double(12.5);
String s1 = String.valueOf(d1);
System.out.println(s1);
}
}
5)String 类型 —> 基本数据类型、包装类 , 调用包装类的 parseXxx()
// 错误的情况,可能会报错
// int num1 = (int)str1;
// Integer in1 = (Integer)str1;发生强转的是str1和 Integer 必须是有子父类关系
可能会报NumberFormatException
int num2 = Integer.parseInt(str1);
System.out.println(num2 + 1); //124
String str2 = “true”,
String str2 = “true”;
Boolean b1 = Boolean.parseBoolean(str2);
System.out.println(b1);false
package com.zhou.java;
import org.junit.Test;
//String 类型 ---> 基本数据类型、包装类 , 调用包装类的 parseXxx()
public class WrapperTest {
@Test
public void test5(){
String str1="123";
//错误的情况:
// String str1="123abc";
int i = Integer.parseInt(str1);
System.out.println(i);
String str2="true";
boolean b = Boolean.parseBoolean(str2);
System.out.println(b);
}
}
8、练习
8.1继承性练习
8.2向下转型练习
8.3多态练习
在赋值的时候,体现为多态性
是Student,就调studen方法,若是Graduate,那就调graduate,是Person就调Person中的方法
属于多态
先写范围小的
package com.exer.java;
public class InstanceTest{
public static void main(String[] args) {
InstanceTest t1 = new InstanceTest();
t1.method(new Student());
}
public void method(Person e){
String info = e.getInfo();
System.out.println(info);
if ( e instanceof Graduate){
System.out.println(" a graduate student");
System.out.println(" a student");
System.out.println(" a person");
}else if( e instanceof Student){
System.out.println(" a student");
System.out.println(" a person");
}else {
System.out.println(" a person");
}
}
}
class Person{
protected String name="person";
protected int age=50;
public String getInfo(){
return "name:"+name+",age:"+age;
}
}
class Student extends Person {
protected String school="pku";
public String getInfo(){
return "name:"+name+",age:"+age+"school:"+school;
}
}
class Graduate extends Student {
public String mjor="it";
public String getInfo(){
return "name:"+name+",age:"+age+"school:"+school+"major:"+mjor;
}
}
8.3==与equals练习
比地址
为什么是true?
8.4Object类练习
8.4包装类练习
9、面试题
9.1、区分方法的重载与重写:
重载:1方法名相同,形参列表不同(形参个数不同、形参类型不同)
重写:发生在继承中,方法名与父类方法名相同,形参列表相同。
9.2、多态是编译时行为还是运行时行为?如何证明?
运行时才知道真正创建的对象是谁,进而知道调的子类的方法是谁
9.3、final,finall,finalize的区别?
9.4、==和equals的区别?
9.5、包装类
println()里面放char型数组,输出的是内容,除了char型数组都是地址值
Integer m=1;此处不是new的方式
Integer n=1;
在Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[]
保存了从-128到127范围的正数,如果我们使用自动装箱的方式,给Integer赋值的范围在-128到127范围i内,可以直接使用数组中的元素,不用再去new了