241.面向对象(中)-每天一考
1.构造器的作用是什么?使用中有哪些注意点(>=3条)
①创建对象 ②初始化对象结构
注意事项:
1.构造器的名称必须与类名同名,包括大小写。
2.构造器没有返回值,不能写void,也不能写return。
3.构造器的参数:一般是对象初始化的前提条件。
4.用new调用,且对象一旦建立,构造器就立刻运行,且只运行一次,创建新的对象需要再次使用new调用。一般方法可被调用多次。
5.类一定有构造器。
6.如果类没有声明任何的构造器,java编译器会自动插入默认构造器(无参构造)。
7.默认构造器是无参构造,方法体是空的构造器,且默认构造器的访问权限随着所属类的访问权限变化而变化。如,若类被public修饰,则默认构造器也带public修饰符。
8.默认构造器是看不到的,一旦自己写上构造器则默认构造器就没有了。自己写的构造器叫做自定义构造器,即便写的是无参构造器,也算自定义构造器,而不是默认构造器。
9.如果类声明了构造器,Java编译器将不再提供默认构造器。若手动没写出无参构造器,却调用了无参构造器,将会报错。
10.构造器是可以重载的,重载的目的是为了使用方便,重载规则与方法重载规则相同。
11.构造器是不能继承的!虽然叫做构造方法,但实际上它不是常说的一般方法。
12.子类继承父类,那么子类型构造器默认调用父类型的无参数构造器。
13.子类构造器一定要调用父类构造器,如果父类中没有无参构造器,则必须使用super(有参数的),来调用父类有参的构造器。
2.关于类的属性的赋值,有几种赋值的方式。谈谈赋值的先后顺序
默认初始化-显式初始化-构造器中初始化-对象.方法 或 对象.属性 给属性赋值
3.this关键字可以用来调用哪些结构,简单说明一下其使用。
this:属性、方法、构造器
this:理解为当前对象,当前正在创建的对象
4.Java中目前学习涉及到的四种权限修饰符都有什么?并说明各自的权限范围
private int age;
private void eat(){}
5.创建Circle类,提供私有的radius属性,提供相应的get和set方法,提供求圆面积的方法。
private double radius;
public void setRadius(double radius){
this.radius = radius;
}
public double getRadius(){
return radius;
}
public double findArea(){
return 3.14 * getRadius() * radius;
}
242.面向对象(中)-复习:封装性与构造器
243.面向对象(中)-复习:this、package、import
244.面向对象(中)-Eclipse常用快捷键1
package com.atguigu.java;
import java.sql.Date;
import java.util.ArrayList;
import java.util.HashMap;
/*
* Eclipse中的快捷键:
* 1.补全代码的声明:alt + /
* 2.快速修复: ctrl + 1
* 3.批量导包:ctrl + shift + o
* 4.使用单行注释:ctrl + /
* 5.使用多行注释: ctrl + shift + /
* 6.取消多行注释:ctrl + shift + \
* 7.复制指定行的代码:ctrl + alt + down 或 ctrl + alt + up
* 8.删除指定行的代码:ctrl + d
* 9.上下移动代码:alt + up 或 alt + down
* 10.切换到下一行代码空位:shift + enter
* 11.切换到上一行代码空位:ctrl + shift + enter
* 12.如何查看源码:ctrl + 选中指定的结构 或 ctrl + shift + t
* 13.退回到前一个编辑的页面:alt + left
* 14.进入到下一个编辑的页面(针对于上面那条来说的):alt + right
* 15.光标选中指定的类,查看继承树结构:ctrl + t
* 16.复制代码: ctrl + c
* 17.撤销: ctrl + z
* 18.反撤销: ctrl + y
* 19.剪切:ctrl + x
* 20.粘贴:ctrl + v
* 21.保存: ctrl + s
* 22.全选:ctrl + a
* 23.格式化代码: ctrl + shift + f
* 24.选中数行,整体往后移动:tab
* 25.选中数行,整体往前移动:shift + tab
* 26.在当前类中,显示类结构,并支持搜索指定的方法、属性等:ctrl + o
* 27.批量修改指定的变量名、方法名、类名等:alt + shift + r
* 28.选中的结构的大小写的切换:变成大写: ctrl + shift + x
* 29.选中的结构的大小写的切换:变成小写:ctrl + shift + y
* 30.调出生成getter/setter/构造器等结构: alt + shift + s
* 31.显示当前选择资源(工程 or 文件)的属性:alt + enter
* 32.快速查找:参照选中的Word快速定位到下一个 :ctrl + k
*
* 33.关闭当前窗口:ctrl + w
* 34.关闭所有的窗口:ctrl + shift + w
* 35.查看指定的结构使用过的地方:ctrl + alt + g
* 36.查找与替换:ctrl + f
* 37.最大化当前的View:ctrl + m
* 38.直接定位到当前行的首位:home
* 39.直接定位到当前行的末位:end
*/
public class EclipseKeys {
final double PROJECT_ACCOUNT_ID = 3.14;
public static void main(String[] args) {
String s = new String();
String str = new String();
char c = str.charAt(0);
int num = 1;
ArrayList list123 = new ArrayList();
list123.add(123);
list123.add(123);
list123.add(123);
list123.add(123);
list123.add(123);
list123.add(123);
HashMap map = null;
map = new HashMap();
Date date = new Date(32423324L);
HashMap map1 = null;
}
}
class User{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
}
245.面向对象(中)-Eclipse常用快捷键2
246.面向对象(中)-Eclipse常用快捷键3
247.面向对象(中)-回顾Bank练习的难点
项目二
248.面向对象(中)-项目二功能演示
249.面向对象(中)-项目二软件结构设计
250.面向对象(中)-项目二CMUtility工具类的功能介绍
251.面向对象(中)-项目二:Customer类的设计
252.面向对象(中)-项目二:CustomerList类的设计
253.面向对象(中)-项目二:CustomerView的整体框架搭建
254.面向对象(中)-项目二:CustomerView退出功能的实现
255.面向对象(中)-项目二:CustomerView客户列表功能实现
256.面向对象(中)-项目二:CustomerView添加客户功能实现
257.面向对象(中)-项目二:CustomerView修改客户功能的实现
258.面向对象(中)-项目二:CustomerView删除客户功能的实现
259.面向对象(中)-项目二:总结
继承
260.面向对象(中)-继承性的理解
为什么要有继承?
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中, 那么多个类无需再定义这些属性和行为,只要继承那个类即可。
此处的多个类称为子类(派生类)
,单独的这个类称为父类(基类或超类)
。可以理解为:“子类 is a 父类”
类继承语法规则:
class Subclass extends SuperClass{ }
作用:
继承的出现减少了代码冗余,提高了代码的复用性。
继承的出现,更有利于功能的扩展。
继承的出现让类与类之间产生了关系,提供了多态的前提。
注意:不要仅为了获取其他类中某个功能而去继承
261.面向对象(中)-继承性的使用
- 子类继承了父类,就继承了父类的方法和属性。
- 在子类中,可以使用父类中定义的方法和属性,也可以创建自己特有的新的属性和方法。
- 在Java 中,继承的关键字用的是“extends”,即子类不是父类的子集,而是对父类的“扩展”。
关于继承的规则:仍然认为获取了父类中的私有结构,只是因为封装性的影响,子类不能直接访问父类中私有的(private)的成员变量和方法。
262.面向对象(中)-继承性的再说明
- 一个类可以被多个子类继承
- Java中类的单继承性:一个类只能有一个父类
- 子父类是相对的概念
- 子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
263.面向对象(中)-Object类的理解
如果没有显示的声明一个类的父类的话,则此类继承于java.lang.Object类
所有的java类(除java.lang.Object外)都直接或间接于java.lang.Object类
意味着,所有的java类都具有java.lang.Object类中的功能
264.面向对象(中)-每天一考
265.面向对象(中)-复习:项目二
266.面向对象(中)-复习:继承性
267.面向对象(中)-继承性练习1:基本操作
268.面向对象(中)-继承性练习2:基本操作
269.面向对象(中)-Eclipse Debug的使用
270.面向对象(中)-项目二中使用Debug调试
271.面向对象(中)-解决Debug中step into功能失灵问题
272.面向对象(中)-方法重写的理解
定义:在子类中可以根据需要对从父类中继承来的方法进行改造,也称
为方法的重置、覆盖
。在程序执行时,子类的方法将覆盖父类的方法。
要求:
1.子类重写的方法必须
和父类被重写的方法具有相同的方法名称、参数列表
2.子类重写的方法的返回值类型不能大于
父类被重写的方法的返回值类型
3.子类重写的方法使用的访问权限不能小于
父类被重写的方法的访问权限
4.子类不能重写父类中声明为private权限的方法
5.子类方法抛出的异常不能大于父类被重写方法的异常
注意:
子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。
273.面向对象(中)-方法重写的细节
package com.atguigu.java1;
/*
* 方法的重写(override / overwrite)
*
* 1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
*
* 2.应用:重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法。
*
* 3. 重写的规定:
* 方法的声明: 权限修饰符 返回值类型 方法名(形参列表) throws 异常的类型{
* //方法体
* }
* 约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法
* ① 子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
* ② 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
* >特殊情况:子类不能重写父类中声明为private权限的方法
* ③ 返回值类型:
* >父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
* >父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
* >父类被重写的方法的返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须也是double)
* ④ 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型(具体放到异常处理时候讲)
* **********************************************************************
* 子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(不是重写)。
*
*/
public class PersonTest {
public static void main(String[] args) {
Student s = new Student("计算机科学与技术");
s.eat();
s.walk(10);
System.out.println("**************");
s.study();
Person p1 = new Person();
p1.eat();
}
}
274.面向对象(中)-方法重写的练习
275.面向对象(中)-测试四种不同的权限修饰符
276.面向对象(中)-super调用属性和方法
在Java类中使用super来调用父类中的指定操作:
super可用于访问父类中定义的属性
super可用于调用父类中定义的成员方法
super可用于在子类构造器中调用父类的构造器
注意:
尤其当子父类出现同名成员时,可以用super表明调用的是父类中的成员
super的追溯不仅限于直接父类
super和this的用法相像,this代表本类对象的引用,super代表父类的内存 空间的标识
package com.atguigu.java3;
/*
* super关键字的使用
* 1.super理解为:父类的
* 2.super可以用来调用:属性、方法、构造器
*
* 3.super的使用:调用属性和方法
*
* 3.1 我们可以在子类的方法或构造器中。通过使用"super.属性"或"super.方法"的方式,显式的调用
* 父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super."
* 3.2 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的
* 使用"super.属性"的方式,表明调用的是父类中声明的属性。
* 3.3 特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的
* 使用"super.方法"的方式,表明调用的是父类中被重写的方法。
*
* 4.super调用构造器
* 4.1 我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
* 4.2 "super(形参列表)"的使用,必须声明在子类构造器的首行!
* 4.3 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现
* 4.4 在构造器的首行,没有显式的声明"this(形参列表)"或"super(形参列表)",则默认调用的是父类中空参的构造器:super()
* 4.5 在类的多个构造器中,至少有一个类的构造器中使用了"super(形参列表)",调用父类中的构造器
*/
public class SuperTest {
public static void main(String[] args) {
Student s = new Student();
s.show();
System.out.println();
s.study();
Student s1 = new Student("Tom", 21, "IT");
s1.show();
System.out.println("************");
Student s2 = new Student();
}
}
277.面向对象(中)-super调用构造器
子类中所有的构造器默认
都会访问父类中空参数
的构造器
当父类中没有空参数的构造器时,子类的构造器必须通过this(参 数列表)
或者super(参数列表)
语句指定调用本类或者父类中相应的 构造器。同时,只能”二选一”,且必须放在构造器的首行
如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错
278.面向对象(中)-子类对象实例化全过程
279.面向对象(中)-继承和super课后练习
多态
280.面向对象(中)-多态性的使用
创建Person类
package com.atguigu.java4;
public class Person {
String name;
int age;
int id = 1001;
public void eat(){
System.out.println("人:吃饭");
}
public void walk(){
System.out.println("人:走路");
}
}
创建Man继承Person
package com.atguigu.java4;
public class Man extends Person{
//获得Person中属性和方法的同时,添加Man特有的属性和方法
boolean isSmoking;//是否抽烟
int id = 1002;
public void earnMoney(){
System.out.println("男人负责挣钱养家");
}
//重写eat方法
public void eat(){
System.out.println("男人多吃肉,长肌肉");
}
public void walk(){
System.out.println("男人霸气的走路");
}
}
创建Woman继承Person
package com.atguigu.java4;
public class Woman extends Person{
boolean isBeauty;//是不是美女
public void goShopping(){
System.out.println("女人喜欢购物");
}
public void eat(){
System.out.println("女人少吃,为了减肥");
}
public void walk(){
System.out.println("女人窈窕的走路");
}
}
通过测试说明叫多态性
package com.atguigu.java4;
/*
* 面向对象特征之三:多态性
*
* 1.理解多态性:可以理解为一个事物的多种形态。
* 2.何为多态性:
* 对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
*
* 3. 多态的使用:虚拟方法调用
* 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
* 总结:编译,看左边;运行,看右边。
*
* 4.多态性的使用前提: ① 类的继承关系 ② 方法的重写
*
* 5.对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
*/
public class PersonTest {
public static void main(String[] args) {
//最原始的调用
Person p1 = new Person();
p1.eat();
Man man = new Man();
man.eat();
man.age = 25;
man.earnMoney();
//*************************************************
//对象的多态性:父类的引用指向子类的对象
Person p2 = new Man();
// Person p3 = new Woman();
//多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法 ---虚拟方法调用
p2.eat();//打印“男人多吃肉,长肌肉”
p2.walk();
//只能调用Person里面声明的方法
//编译看左边,没有的方法会报错。执行看右边,实际执行重写后的方法
// p2.earnMoney();
System.out.println(p2.id);//1001
}
}
281.面向对象(中)-多态性的使用举例
如果没有多态性,还需要写另外两个重载的func方法
package com.atguigu.java4;
import java.sql.Connection;
//多态性的使用举例一:
public class AnimalTest {
public static void main(String[] args) {
AnimalTest test = new AnimalTest();
//调用func方法,首先需要传一个实例
test.func(new Dog());//相当于Animal animal = new Dog();
test.func(new Cat());//相当于Animal animal = new Cat();
}
public void func(Animal animal){//Animal animal = new Dog();
animal.eat();
animal.shout();
if(animal instanceof Dog){
Dog d = (Dog)animal;
d.watchDoor();
}
}
//没有多态性调用时
// 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("动物:叫");
}
}
//dog子类
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
public void shout(){
System.out.println("汪!汪!汪!");
}
public void watchDoor(){
System.out.println("看门");
}
}
//cat子类
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
public void shout(){
System.out.println("喵!喵!喵!");
}
}
//举例二:
class Order{
public void method(Object obj){
}
}
//举例三:
class Driver{
public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection();
//规范的步骤去操作数据
// conn.method1();
// conn.method2();
// conn.method3();
}
}
282.面向对象(中)-多态性不适用于属性
调用时打印父类中定义的属性
属性没有重写,所有多态只适用于属性
283.面向对象(中)-虚拟方法调用的再理解
虚拟方法调用(多态情况下)
子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父 类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法 确定的。
多态是运行时行为
284.面向对象(中)-每天一考
-
什么是多态性?什么是虚拟方法调用?
对象的多态性:父类的引用指向子类的对象。
Person p = new Man();
p.eat();
调用方法时,编译时看左边,运行时看右边。 -
一个类可以有几个直接父类?(只有一个)一个父类可有多少个子类?(多个)子类能获取直接父类的父类中的结构吗?(可以)子类能否获取父类中private权限的属性或方法?(可以的)
封装性解决能不能调用,继承解决能不能获取
A is a B -
方法的重写(override/overwrite)的具体规则有哪些?
方法名、形参列表相同
权限修饰符
返回值
抛出的异常 -
super调用构造器,有哪些具体的注意点
this(形参列表):本类重载的其它的构造器
super(形参列表):调用父类中指定的构造器
n n – 1 1 -
在下面的代码结构中:使用关键字:this,super;方法的重写;继承;
285.面向对象(中)-复习:重写与super
1.什么是方法的重写(override或overwrite)
子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法
2.区分重载和重写
重载:不表现为多态性
重写:表现为多态性
3.super关键字可以理解为
父类的
4.super可以调用的结构:
属性、方法、构造器
5.super调用属性、方法
1.我们可以在子类的方法或构造器中。通过使用"super.属性"或"super.方法"的方式,显式的调用
父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super."
2.特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的
使用"super.属性"的方式,表明调用的是父类中声明的属性。
3.特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用"super.方法"的方式,表明调用的是父类中被重写的方法。
286.面向对象(中)-复习:子类对象实例化过程及多态性
子类对象实例化全过程
- 从结果上来看:(继承性)
子类继承父类以后,就获取了父类中声明的属性或方法
创建子类的对象,在堆空间中,就会加载所有父类中声明的属性。 - 从过程上来看:
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器,只到调用了java.lang.Object类中空参的构造器为止。正因为加载过所有父类的结构,所以才可以看到内存中父类中的结构,子类对象才可以考虑进行调用。 - 明确:虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象
多态性的理解:可以理解为一个事务的多种形态
何为多态性:父类的引用指向子类的对象(或子类的对象赋给父类使用)
多态性的使用:虚拟方法调用
有了对象的多态性之后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法
总结:编译看左边,运行看右边
287.面向对象(中)-复习:向下转型的使用
288.面向对象(中)-复习:instanceof关键字的使用
为了避免在向下转型时出现ClassCastException的异常
x instanceof A:检验x是否为类A的对象,返回值为boolean型。
要求x所属的类与类A必须是子类和父类的关系,否则编译错误。
如果x属于类A的子类B,x instanceof A值也为true。
public class Person extends Object {…}
public class Student extends Person {…}
public class Graduate extends Person {…}
-------------------------------------------------------------------
public void method1(Person e) {
if (e instanceof Person)
// 处理Person类及其子类对象
if (e instanceof Student)
//处理Student类及其子类对象
if (e instanceof Graduate)
//处理Graduate类及其子类对象
}
289.面向对象(中)-复习:向下转型的几个常见问题
//练习:
//问题一:编译时通过,运行时不通过
//举例一:
Person p3 = new Woman();
Man m3 = (Man)p3;
//举例二:
Person p4 = new Person();
Man m4 = (Man)p4;
//问题二:编译通过,运行时也通过
Object obj = new Woman();
Person p = (Person)obj;
//问题三:编译不通过
Man m5 = new Woman();
String str = new Date();
Object o = new Date();
String str1 = (String)o;
290.面向对象(中)-多态练习:调用方法和属性
package com.atguigu.exer;
/*
* 练习:
* 1.若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,
* 系统将不可能把父类里的方法转移到子类中:编译看左边,运行看右边
*
* 2.对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,
* 这个实例变量依然不可能覆盖父类中定义的实例变量:编译运行都看左边
*/
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 FieldMethodTest {
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
}
}
291.面向对象(中)-多态练习:基本操作
package com.atguigu.exer;
/*
* 建立InstanceTest 类,在类中定义方法method(Person e);
在method中:
(1)根据e的类型调用相应类的getInfo()方法。
(2)根据e的类型执行:
如果e为Person类的对象,输出:
“a person”;
如果e为Student类的对象,输出:
“a student”
“a person ”
如果e为Graduate类的对象,输出:
“a graduated student”
“a student”
“a person”
*
*/
public class InstanceTest {
public static void main(String[] args) {
InstanceTest test = new InstanceTest();
test.method(new Student());
}
public void method(Person e){
//虚拟方法调用
String info = e.getInfo();
System.out.println(info);
//方式一
// if(e instanceof Graduate){
// System.out.println("a graduated 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");
// }
//方式二
if(e instanceof Graduate){
System.out.println("a graduated student");
}
if(e instanceof Student){
System.out.println("a student");
}
if(e instanceof Person){
System.out.println("a person");
}
}
}
class Person {
protected String name = "person";
protected int age = 50;
public String getInfo() {
return "Name: " + name + "\n" + "age: " + age;
}
}
class Student extends Person {
protected String school = "pku";
public String getInfo() {
return "Name: " + name + "\nage: " + age + "\nschool: " + school;
}
}
class Graduate extends Student {
public String major = "IT";
public String getInfo() {
return "Name: " + name + "\nage: " + age + "\nschool: " + school + "\nmajor:" + major;
}
}
292.面向对象(中)-多态练习:几何图形
package com.atguigu.exer1;
public class GeometricObject {//几何图形
protected String color;
protected double weight;
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public GeometricObject(String color, double weight) {
super();
this.color = color;
this.weight = weight;
}
public double findArea(){
return 0.0;
}
}
package com.atguigu.exer1;
/*
* 定义一个测试类GeometricTest,
* 编写equalsArea方法测试两个对象的面积是否相等(注意方法的参数类型,利用动态绑定技术),
* 编写displayGeometricObject方法显示对象的面积(注意方法的参数类型,利用动态绑定技术)。
*/
public class GeometricTest {
public static void main(String[] args) {
GeometricTest test = new GeometricTest();
Circle c1 = new Circle(3.3, "white", 1.0);
test.displayGeometricObject(c1);
Circle c2 = new Circle(3.3, "white", 1.0);
test.displayGeometricObject(c2);
boolean isEquals = test.equalsArea(c1, c2);
System.out.println("c1 和 c2的面积是否相等:" + isEquals);
MyRectangle rect = new MyRectangle(2.1, 3.4, "red", 2.0);
test.displayGeometricObject(rect);
}
public void displayGeometricObject(GeometricObject o){//GeometricObject o = new Circle(...)
System.out.println("面积为:" + o.findArea());
}
//测试两个对象的面积是否相等
public boolean equalsArea(GeometricObject o1,GeometricObject o2){
return o1.findArea() == o2.findArea();
}
}
293.面向对象(中)-多态练习:重写方法
package com.atguigu.exer;
//考查多态的笔试题目:
public class InterviewTest1 {
public static void main(String[] args) {
Base1 base = new Sub1();
base.add(1, 2, 3);
Sub1 s = (Sub1)base;
s.add(1,2,3);
}
}
class Base1 {
public void add(int a, int... arr) {
System.out.println("base1");
}
}
class Sub1 extends Base1 {
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");
}
}
294.面向对象(中)-Object类的结构剖析
- clone()
保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。- getClass()
final方法,返回Class类型的对象,反射来获取对象。- toString()
该方法用得比较多,一般子类都有覆盖,来获取对象的信息。- finalize()
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。- equals()
比较对象的内容是否相等- hashCode()
该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。- wait()
wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
调用该方法后当前线程进入睡眠状态,直到以下事件发生。
其他线程调用了该对象的notify方法。
其他线程调用了该对象的notifyAll方法。
其他线程调用了interrupt中断该线程。
时间间隔到了。
此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。- notify()
该方法唤醒在该对象上等待的某个线程。- notifyAll()
该方法唤醒在该对象上等待的所有线程。
package com.atguigu.java1;
/*
* java.lang.Object类
* 1.Object类是所有Java类的根父类
* 2.如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
* 3.Object类中的功能(属性、方法)就具有通用性。
* 属性:无
* 方法:equals() / toString() / getClass() /hashCode() / clone() / finalize()
* wait() 、 notify()、notifyAll()
*
* 4. Object类只声明了一个空参的构造器
*
*/
public class ObjectTest {
public static void main(String[] args) {
Order order = new Order();
System.out.println(order.getClass().getSuperclass());
}
}
class Order{
}
==和equals()
295.面向对象(中)-==运算符的回顾
package com.atguigu.java1;
import java.util.Date;
/*
* 面试题: == 和 equals() 区别
* 一、回顾 == 的使用:
* == :运算符
* 1. 可以使用在基本数据类型变量和引用数据类型变量中
* 2. 如果比较的是基本数据类型变量:比较两个变量保存的数据是否相等。(不一定类型要相同)
* 如果比较的是引用数据类型变量:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体
* 补充: == 符号使用时,必须保证符号左右两边的变量类型一致。
*/
public class EqualsTest {
public static void main(String[] args) {
//基本数据类型
int i = 10;
int j = 10;
double d = 10.0;
System.out.println(i == j);//true
System.out.println(i == d);//true
boolean b = true;
// System.out.println(i == b);
char c = 10;
System.out.println(i == c);//true
char c1 = 'A';
char c2 = 65;
System.out.println(c1 == c2);//true
}
}
296.面向对象(中)-equals()的使用
package com.atguigu.java1;
import java.util.Date;
/*
* 二、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()进行重写.
* 重写的原则:比较两个对象的实体内容是否相同.
*/
public class EqualsTest {
public static void main(String[] args) {
//引用类型:
Customer cust1 = new Customer("Tom",21);
Customer cust2 = new Customer("Tom",21);
System.out.println(cust1 == cust2);//false
String str1 = new String("atguigu");
String str2 = new String("atguigu");
System.out.println(str1 == str2);//false
System.out.println("****************************");
System.out.println(cust1.equals(cust2));//false--->true
//调用Object类中定义的equals()和==的作用是相同的
System.out.println(str1.equals(str2));//true
//像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。
Date date1 = new Date(32432525324L);
Date date2 = new Date(32432525324L);
System.out.println(date1.equals(date2));//true
}
}
297.面向对象(中)-重写equals()
String的equals
public boolean equals(Object anObject) {
//判断引用地址
if (this == anObject) {
return true;
}
if (anObject instanceof String) {//判断是否为String
//向下转型,强转为String
//形参是anObject,实参是String类型,传入类型会自动类型提升,不强转的话,“编译”的时候点不出来String的结构
//“运行”的时候,实际上anObject形参收到的是String类型的对象,运行的时候,这里强转不强转无所谓,问题时,编译和运行不一样,起码要让代码写上去。
String anotherString = (String)anObject;
int n = value.length;//当前字符串的长度
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;
}
298.面向对象(中)-总结==与equals()
- == 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型就是比较内存地址
- equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是==;
- 我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点。
- 具体要看自定义类里有没有重写Object的equals方法来判断。
- 通常情况下,重写equals方法,会比较类中的相应属性是否都相等。
299.面向对象(中)-equals()练习1:代码实现
编写Order类,有int型的orderId,String型的orderName,相应的 getter()和setter()方法,两个参数的构造器,重写父类的equals()方法: public boolean equals(Object obj),并判断测试类中创建的两个对象是否相等。
package com.atguigu.exer2;
/*
* 编写Order类,有int型的orderId,String型的orderName,
* 相应的getter()和setter()方法,两个参数的构造器,
* 重写父类的equals()方法:public boolean equals(Object obj),
* 并判断测试类中创建的两个对象是否相等。
*/
public class OrderTest {
public static void main(String[] args) {
Order order1 = new Order(1001, "AA");
Order order2 = new Order(1001, new String("BB"));
System.out.println(order1.equals(order2));
Order order3 = new Order(1001, "BB");
System.out.println(order2.equals(order3));
// String s1 = "BB";
// String s2 = "BB";
// System.out.println(s1 == s2);//true
}
}
class Order{
private int orderId;
private String orderName;
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public Order(int orderId, String orderName) {
super();
this.orderId = orderId;
this.orderName = orderName;
}
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj instanceof Order){
Order order = (Order)obj;
//正确的:
return this.orderId == order.orderId &&
this.orderName.equals(order.orderName);
//错误的:
// return this.orderId == order.orderId &&
// this.orderName == order.orderName;
}
return false;
}
}
300.面向对象(中)-equals()练习2:代码实现
请根据以下代码自行定义能满足需要的MyDate类,在MyDate类中覆盖 equals方法,使其判断当两个MyDate类型对象的年月日都相同时,结果 为true,否则为false。 public boolean equals(Object o)
package com.atguigu.exer2;
public class MyDateTest {
public static void main(String[] args) {
MyDate m1 = new MyDate(14, 3, 1976);
MyDate m2 = new MyDate(14, 3, 1976);
if (m1 == m2) {
System.out.println("m1==m2");
} else {
System.out.println("m1!=m2"); // m1 != m2
}
if (m1.equals(m2)) {
System.out.println("m1 is equal to m2");// m1 is equal to m2
} else {
System.out.println("m1 is not equal to m2");
}
}
}
class MyDate{
private int day;
private int month;
private int year;
public MyDate(int day, int month, int year) {
super();
this.day = day;
this.month = month;
this.year = year;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj instanceof MyDate){
MyDate myDate = (MyDate)obj;
return this.day == myDate.day && this.month == myDate.month &&
this.year == myDate.year;
}
return false;
}
// @Override
// public boolean equals(Object obj) {
// if (this == obj)
// return true;
// if (obj == null)
// return false;
// if (getClass() != obj.getClass())
// return false;
// MyDate other = (MyDate) obj;
// if (day != other.day)
// return false;
// if (month != other.month)
// return false;
// if (year != other.year)
// return false;
// return true;
// }
}
301.面向对象(中)-toString()的使用
package com.atguigu.java1;
import java.util.Date;
/*
* Object类中toString()的使用:
*
* 1. 当我们输出一个对象的引用时,实际上就是调用当前对象的toString()
*
* 2. Object类中toString()的定义:
* public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
*
* 3. 像String、Date、File、包装类等都重写了Object类中的toString()方法。
* 使得在调用对象的toString()时,返回"实体内容"信息
*
* 4. 自定义类也可以重写toString()方法,当调用此方法时,返回对象的"实体内容"
*/
public class ToStringTest {
public static void main(String[] args) {
Customer cust1 = new Customer("Tom",21);
System.out.println(cust1.toString());//输出内存地址值(虚拟地址):com.atguigu.java1.Customer@15db9742-->Customer[name = Tom,age = 21]
System.out.println(cust1);//com.atguigu.java1.Customer@15db9742-->Customer[name = Tom,age = 21]
String str = new String("MM");
System.out.println(str);//MM
Date date = new Date(4534534534543L);
System.out.println(date.toString());//Mon Sep 11 08:55:34 GMT+08:00 2113
}
}
302.面向对象(中)-Object类综合练习
package com.atguigu.exer3;
public class GeometricObject {
protected String color;
protected double weight;
public GeometricObject() {
super();
this.color = "white";
this.weight = 1.0;
}
public GeometricObject(String color, double weight) {
super();
this.color = color;
this.weight = weight;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
}
package com.atguigu.exer3;
public class Circle extends GeometricObject {
private double radius;
public Circle() {
super();
radius = 1.0;
// color = "white";
// weight = 1.0;
}
public Circle(double radius) {
super();
this.radius = radius;
}
public Circle(double radius,String color,double weight) {
super(color,weight);
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
//求圆的面积
public double findArea(){
return 3.14 * radius * radius;
}
//比较两个圆的半径是否相等,如相等,返回true。
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj instanceof Circle){
Circle c = (Circle)obj;
return this.radius == c.radius;
}
return false;
}
@Override
public String toString() {
return "Circle [radius=" + radius + "]";
}
}
package com.atguigu.exer3;
/*
* 写一个测试类,创建两个Circle对象,判断其颜色是否相等;
* 利用equals方法判断其半径是否相等;利用toString()方法输出其半径。
*/
public class CircleTest {
public static void main(String[] args) {
Circle circle1 = new Circle(2.3);
Circle circle2 = new Circle(3.3, new String("white"), 2.0);
System.out.println("颜色是否相等:" + circle1.getColor().equals(circle2.getColor()));
System.out.println("半径是否相等:" + circle1.equals(circle2));
System.out.println(circle1);
System.out.println(circle2.toString());
}
}
303.面向对象(中)-单元测试方法的使用
package com.atguigu.java2;
import java.util.Date;
import org.junit.Test;
/*
* Java中的JUnit单元测试
*
* 步骤:
* 1.选中当前工程 - 右键选择:build path - add libraries - JUnit 4 - 下一步
* 2.创建Java类,进行单元测试。
* 此时的Java类要求:① 此类是public的 ②此类提供公共的无参的构造器
* 3.此类中声明单元测试方法。
* 此时的单元测试方法:方法的权限是public,没有返回值,没有形参
*
* 4.此单元测试方法上需要声明注解:@Test,并在单元测试类中导入:import org.junit.Test;
*
* 5.声明好单元测试方法以后,就可以在方法体内测试相关的代码。
* 6.写完代码以后,左键双击单元测试方法名,右键:run as - JUnit Test
*
* 说明:
* 1.如果执行结果没有任何异常:绿条
* 2.如果执行结果出现异常:红条
*/
public class JUnitTest {
int num = 10;
@Test
public void testEquals(){
String s1 = "MM";
String s2 = "MM";
System.out.println(s1.equals(s2));
//ClassCastException的异常
// Object obj = new String("GG");
// Date date = (Date)obj;
System.out.println(num);
show();
}
public void show(){
num = 20;
System.out.println("show()....");
}
@Test
public void testToString(){
String s2 = "MM";
System.out.println(s2.toString());
}
}
304.面向对象(中)-包装类的理解
针对八种基本数据类型定义相应的引用类型—包装类(封装类)
有了类的特点,就可以调用类中的方法,Java才是真正的面向对象
305.面向对象(中)-基本数据类型转换为包装类
package com.atguigu.java2;
import org.junit.Test;
/*
* 包装类的使用:
* 1.java提供了8种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征
* 2.掌握的:基本数据类型、包装类、String三者之间的相互转换
*/
public class WrapperTest {
//基本数据类型 --->包装类:调用包装类的构造器
@Test
public void test1(){
int num1 = 10;
// System.out.println(num1.toString());
Integer in1 = new Integer(num1);
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);
Boolean b2 = new Boolean("TrUe");
System.out.println(b2);
Boolean b3 = new Boolean("true123");
System.out.println(b3);//false
Order order = new Order();
System.out.println(order.isMale);//false
System.out.println(order.isFemale);//null
}
}
class Order{
boolean isMale;
Boolean isFemale;
}
306.面向对象(中)-包装类转换为基本数据类型
public class WrapperTest {
//包装类--->基本数据类型:调用包装类Xxx的xxxValue()
@Test
public void test2(){
Integer in1 = new Integer(12);
int i1 = in1.intValue();
System.out.println(i1 + 1);
Float f1 = new Float(12.3);
float f2 = f1.floatValue();
System.out.println(f2 + 1);
}
}
307.面向对象(中)-新特性:自动装箱与自动拆箱
public class WrapperTest {
//JDK 5.0 新特性:自动装箱 与自动拆箱
@Test
public void test3(){
// int num1 = 10;
// //基本数据类型-->包装类的对象
// method(num1);
//自动装箱:基本数据类型 --->包装类
int num2 = 10;
Integer in1 = num2;//自动装箱
boolean b1 = true;
Boolean b2 = b1;//自动装箱
//自动拆箱:包装类--->基本数据类型
System.out.println(in1.toString());
int num3 = in1;//自动拆箱
}
public void method(Object obj){
System.out.println(obj);
}
}
308.面向对象(中)-基本数据类型包装类与String的相互转换
public class WrapperTest {
//String类型 --->基本数据类型、包装类:调用包装类的parseXxx(String s)
@Test
public void test5(){
String str1 = "123";
//错误的情况:
// int num1 = (int)str1;
// Integer in1 = (Integer)str1;
//可能会报NumberFormatException
int num2 = Integer.parseInt(str1);
System.out.println(num2 + 1);
String str2 = "true1";
boolean b1 = Boolean.parseBoolean(str2);
System.out.println(b1);
}
//基本数据类型、包装类--->String类型:调用String重载的valueOf(Xxx xxx)
@Test
public void test4(){
int num1 = 10;
//方式1:连接运算
String str1 = num1 + "";
//方式2:调用String的valueOf(Xxx xxx)
float f1 = 12.3f;
String str2 = String.valueOf(f1);//"12.3"
Double d1 = new Double(12.4);
String str3 = String.valueOf(d1);
System.out.println(str2);
System.out.println(str3);//"12.4"
}
public void method(Object obj){
System.out.println(obj);
}
}
309.面向对象(中)-包装类常见面试题
package com.atguigu.java2;
import org.junit.Test;
//关于包装类使用的面试题
public class InterviewTest {
@Test
public void test1() {
Object o1 = true ? new Integer(1) : new Double(2.0);
System.out.println(o1);// 1.0
//因为new Integer(1) : new Double(2.0),编译时期1提升为Double类型的1.0
}
@Test
public void test2() {
Object o2;
if (true)
o2 = new Integer(1);
else
o2 = new Double(2.0);
System.out.println(o2);// 1
}
@Test
public void test3() {
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j);//false
//Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],
//保存了从-128~127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在
//-128~127范围内时,可以直接使用数组中的元素,不用再去new了。目的:提高效率
Integer m = 1;
Integer n = 1;
System.out.println(m == n);//true
Integer x = 128;//相当于new了一个Integer对象
Integer y = 128;//相当于new了一个Integer对象
System.out.println(x == y);//false
}
}
310.面向对象(中)-包装类的课后练习
package com.atguigu.exer4;
import java.util.Scanner;
import java.util.Vector;
/*
* 利用Vector代替数组处理:从键盘读入学生成绩(以负数代表输入结束),找出最高分,并输出学生成绩等级。
提示:数组一旦创建,长度就固定不变,所以在创建数组前就需要知道它的长度。
而向量类java.util.Vector可以根据需要动态伸缩。
创建Vector对象:Vector v=new Vector();
给向量添加元素:v.addElement(Object obj); //obj必须是对象
取出向量中的元素:Object obj=v.elementAt(0);
注意第一个元素的下标是0,返回值是Object类型的。
计算向量的长度:v.size();
若与最高分相差10分内:A等;20分内:B等;
30分内:C等;其它:D等
*/
public class ScoreTest {
public static void main(String[] args) {
//1.实例化Scanner,用于从键盘获取学生成绩
Scanner scan = new Scanner(System.in);
//2.创建Vector对象:Vector v=new Vector();相当于原来的数组
Vector v = new Vector();
//3.通过for(;;)或while(true)方式,给Vector中添加数组
int maxScore = 0;
for(;;){
System.out.println("请输入学生成绩(以负数代表输入结束)");
int score = scan.nextInt();
//3.2 当输入是负数时,跳出循环
if(score < 0){
break;
}
if(score > 100){
System.out.println("输入的数据非法,请重新输入");
continue;
}
//3.1 添加操作::v.addElement(Object obj)
//jdk5.0之前:
// Integer inScore = new Integer(score);
// v.addElement(inScore);//多态
//jdk5.0之后:
v.addElement(score);//自动装箱
//4.获取学生成绩的最大值
if(maxScore < score){
maxScore = score;
}
}
//5.遍历Vector,得到每个学生的成绩,并与最大成绩比较,得到每个学生的等级。
char level;
for(int i = 0;i < v.size();i++){
Object obj = v.elementAt(i);
//jdk 5.0之前:
// Integer inScore = (Integer)obj;
// int score = inScore.intValue();
//jdk 5.0之后:
int score = (int)obj;
if(maxScore - score <= 10){
level = 'A';
}else if(maxScore - score <= 20){
level = 'B';
}else if(maxScore - score <= 30){
level = 'C';
}else{
level = 'D';
}
System.out.println("student-" + i + " score is " + score + ",level is " + level);
}
}
}