[Java笔记]day13

   日期:2020-11-09     浏览:86    评论:0    
核心提示:day13review多态性?父类的引用指向子类的对象虚拟方法调用?当我们通过变量名去调用子父类中同名、同参方法时,编译时任务调用的是父类中的方法,实际执行时调用的是子类中重写的方法方法重写(override)的具体规则子类中重写的方法名、形参列表与父类中的相同子类中重写方法的权限修饰符不小于父类中的方法子类中重写方法抛出的异常不大于父类方法中抛出的异常子类中重写方法的返回值不大于父类方法的返回值,具体表现为:当父类方法返回值为void或基本数据类型时,子类重写方法的返

day13

review

  1. 多态性?

父类的引用指向子类的对象

  1. 虚拟方法调用?

当我们通过变量名去调用子父类中同名、同参方法时,编译时任务调用的是父类中的方法,实际执行时调用的是子类中重写的方法

  1. 方法重写(override)的具体规则
  • 子类中重写的方法名形参列表与父类中的相同
  • 子类中重写方法的权限修饰符不小于父类中的方法
  • 子类中重写方法抛出的异常不大于父类方法中抛出的异常
  • 子类中重写方法的返回值不大于父类方法的返回值,具体表现为:
    • 当父类方法返回值为void基本数据类型时,子类重写方法的返回值必须父类中的相同
    • 当父类方法的返回值为引用数据类型A时,子类重谢方法的返回值为相同的引用数据类型A或者A的子类

开发中重写时,经常直接复制父类方法声明或者用快捷键补全

  1. super

调用父类中指定的构造器

  1. 为什么super()this()调用语句只能作为构造器中的第一条语句出现?

无论通过哪个构造器创建子类对象,需要保证先初始化父类。
目的:当子类继承父类后,“继承"父类中所有的属性和方法,因此子类有必要知道父类如何为对象进行初始化

instanceof

  1. 向下转型

引入:有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。

  1. 如何调用子类中特有的属性和方法?
    使用强制类型转换符()

强制转换时,可能出现ClassCastException异常,为了避免上述异常,所以引入instacnceof

  1. 使用:a instanceof A

判断对象a是否为类A的实例,如果是,返回true,否则返回false

  1. 使用情景:为了避免在向下转型时,出现ClassCastException异常,因此在向下转型之前先用instacnceof进行判断,一旦返回true,则进行向下转型,否则不进行

  2. 如果a instanceof A == true,则a instanceof B == true, 其中AB子类

  3. 练习

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);
	}
}

public class FeildMethodTest { 
	public static void main(String[] args) { 
		Sub s = new Sub();
		System.out.println(s.count); // 20
		s.display(); // 20
		Base b = s;
		System.out.println(b == s); // true
		System.out.println(b.count); // 10
		b.display(); // 20
	}
}

由上述练习:

  1. 若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中。
  2. 对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量
    上述两点体现为:方法的编译看左边,运行看右边;变量的编译运行都看左边

实战

public class InterviewTest { 

	public static void main(String[] args) { 
		Base base = new Sub();
		base.add(1, 2, 3);  // (1)

		Sub s = (Sub)base;
		s.add(1, 2, 3); // (2)
	}
}

class Base { 
	public void add(int a, int... arr) { 
		System.out.println("base");
	}
}

class Sub extends Base { 

	public void add(int a, int[] arr) { 
		System.out.println("sub_1");
	}

	public void add(int a, int b, int c) { 
		System.out.println("sub_2");
	}

}

// (1)sub_1
// (2)sub_2

Object类

  1. Object是所有类的根父类
  2. 如果在类的声明中未显式地使用extends关键字指明其父类,则默认父类为java.lang.Object
  3. Object类中的属性和方法具有通用性
  • 属性:无
  • 常用方法:
    • equals()
    • toString
    • getClass()
    • hashCode()

  1. Object类中只定义了一个空参的构造器

equals()

  1. 回顾

==的使用

  • ==是一个运算符,可以使用在基本数据类型变量和引用数据类型的变量中
  • 如果比较的是基本数据类型变量,则比较两个变量保存的数据是否相等(不一定类型相同)
  • 如果比较的是引用数据类型变量,则比较两个对象的地址值是否相同,即比较两个引用是否指向同一个对象实体
  • ==使用时,必须保证符号左右两边的变量类型“一致”
  1. equals()
  • equals()是一个方法,而非运算符
  • 只适用于引用数据类型
  • Object类中equals()的定义:与==作用相同,即比较两个对象的地址值是否相同
// Object源码中equals()的实现
public boolean equals(Object obj) { 
	return (this == obj);
}
  • StringDateFile包装类重写Objectequals()方法。重写之后,比较的不再是两个引用的地址是否相同,而是比较两个对象**实体内容(属性)**是否相同
  1. 通常情况下,我们自定义的类如果使用equals()方法时,比较的也是类中实体内容是否相同,因此需要重写Object类中的equals()方法

重写规则:比较两个对象的实体内容是否相同

// String源码中equals()的实现:重写
public boolean equals(Object anObject) { 
    if (this == anObject) { 
    	return true;
    }
    if (anObject instanceof String) { 
    	String anotherString = (String)anObject;
    	int n = value.length;  // String底层是char[]
    	if (n == anotherString.value.length) { 
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) { 
                if (v1[i] != v2[i])
                return false;
                i++;
   			}
    		return true;
    	}
	}
    return false;
}

开发过程中,一般不会手撕equals(),而是使用IDE自动生成

public class EqualsTest { 
	String name;
	int age;
	// IDE自动生成
	@Override
	public boolean equals(Object obj) { 
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		EqualsTest other = (EqualsTest) obj;
		if (age != other.age)
			return false;
		if (name == null) { 
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
}
  1. ==equals()的区别

toString()

  1. 当我们输出一个对象的引用时,实际上就是调用当前对象的toString()方法
  2. ObjecttoString()方法的定义
public String toString() { 
	return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
  1. StringDateFile包装类重写ObjecttoString()方法,重写之后,使得在调用toString()方法时,返回对象的**实体内容(属性)**信息

// String中对于toString的重写

public String toString() { 
	return this;
}

  1. 自定义类也可以重写toString()方法以返回对象的实体信息,当然也可以通过IDE生成
public class ToStringTest { 
	String name;
	int age;
	// IDE自动生成
	@Override
	public String toString() { 
		return "ToStringTest [name=" + name + ", age=" + age + "]";
	}
}

单元测试

  1. build pathadd librariesJUnit 4
  2. 创建Java类进行单元测试
  • 类是public的,
  • 类提供公共的无参构造器
  1. 在此类中声明单元测试的方法
  • 方法的权限是public
  • 返回值为void
  • 方法没有形参
  1. 单元测试方法之上需要声明注解:@Test,并在测试类中导入org.junit.Test
  2. 声明好单元测试方法之后,就可以在方法体内测试相关代码
  3. 写完代码之后,左键双击选中单元测试方法名,右键run as -> JUnit Test

说明:

  • 如果执行结果没有异常:绿条
  • 如果执行结果出现异常:红条

包装类

  1. 八种基本数据类型都定义了相应的引用类型,称之为包装类。

为什么引入包装类?
为了使基本数据类型的变量具有类的特征

对应关系如下

  1. 基本数据类型、包装类、String三者之间的相互转换
  • 基本数据类型–>包装类:自动装箱/调用包装类的构造器
  • 包装类–>基本数据类型:自动拆箱/调用包装类XxxxxxValue()方法
  • 基本数据类型/包装类–>String类型 :
    • 连接运算
    • 调用String类中重载的valueOf(Xxx xxx)方法
  • String类型–>基本数据类型/包装类:调用包装类中的parseXxx()方法

  1. 自动装箱与自动拆箱

JDK 5.0新特性

  • 自动装箱:基本数据类型->包装类
  • 自动拆箱:包装类->基本数据类型
int m = 10;
Integer j = m;  // 自动装箱

Integer i = new Integer(10);
int n = i;  // 自动拆箱
  1. 练习
@Test
public void test1() { 
	Object o1 = true ? new Integer(1) : new Double(2.0);
	System.out.println(o1);  // (1)
}

@Test
public void test2() { 
	Object o2;
	if (true) { 
		o2 = new Integer(1);
	} else { 
		o2 = new Double(2.0);
	}
	System.out.println(o2);  // (2)
}

@Test
public void test3() { 

    Integer i = new Integer(1);
    Integer j = new Integer(1);
    System.out.println(i == j); // (3)

    Integer m = 1;
    Integer n = 1;
    System.out.println(m == n); // (4)

    Integer x = 128;
    Integer y = 128;
    System.out.println(x == y); // (5)
}

// (1)1.0 编译时 int 提升为 double
// (2)1
// (3)false new 出来的对象地址不一样
// (4)true Integer 有一个static Integer cache[], 初始化存储-128~+127的的数字, 自动装箱时不用new
// (5)false 超过上述范围,需要new
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服