2022-07-25 第八组 卢睿 学习心得
JAVA面向对象之多态
今日重点
- 两种多态形式
- 匿名方法
- 编译看左边,运行看右边
- instanceof关键字
- 链表
- 单链表代码
今日心得
今天学了多态,用我自己的话来说就是可以用一个父类的对象调用父类和子类的方法,也容易理解,链表属于数据结构,原理能搞懂,但自己把单链表写出来还是困难,要多研究研究代码。
举例理解一下
狗是动物吗? 是
猫是动物吗? 是
狗是猫吗 不是
多态的形成有3个条件
- 有继承
- 有重写
- 有父类对象指向子类引用
第一种多态形式
向上转移(可以自动转的)
父类 父类对象 = new 子类();
第二种多态形式
向下转型
子类 子类对象 = new 父类();
发生向下转型的前提,要先发生向上转型,才能通过强转
能传任何参的方法
package com.morning;
public class Ch02 {
//无敌方法
public Object show(Object...obj){
return true;
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
public static void main(String[] args) {
Object obj = new Person();
obj = new Ch02();
Ch02 ch02 = new Ch02();
ch02.show("",1,'a',1.2,true,obj);
}
}
匿名对象
语法
new 类名();
功能
和正常的有名字的对象功能是相同的,依然具备了调用属性,方法的功能。
使用场景
多数是用在传参,实参,多数情况下配合构造器使用
好处
节约资源
数组是不是类?
是
- 站在JVM的角度看,是类,在JVM解析数组是,会生成一个数组的类解析数组
- 站在编译角度,不是类,因为没有类名,没有结构
多态
编译看左边,运行看右边
Animal animal = new Cat();
instanceof关键字
判断某一个对象是否是某一个类的实例,返回值是boolean类型
总结一下
/**
* 多态:
* 向上转型:父类对象->子类引用
* 向下转型:子类引用->父类对象,前提:必须先发生向上转型
*
* instanceof:判断某一个对象是不是这个类的实例,返回值为boolean
*
* 方法的重写:
* 重写的方法的返回值可以是被重写方法的返回值的子类。void
*/
链表,数据结构
链表:是一个数据结构
在内存中,数组和链表都是最基本的数据结构,表,或者线性表
线性表
线性的结构,它是一个含有n>=0个结点的有限序列,有且只有一个上一个结点,有且只有一个下一个结点,也就是有头有尾的一条线
单向链表
在维护一个结点的自身的值的同时,还要维护它的下一个值的指向
双向链表
在维护一个结点的自身的值的同时,还要维护它的上一个和下一个值的指向
单链表代码实现
Node类
package com.afternoon.dianlianbiao;
/**
* 单向
*/
public class Node {
private Integer data;
private Node next;
public Integer getData() {
return data;
}
public void setData(Integer data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public Node() {
}
public Node(Integer data, Node next) {
this.data = data;
this.next = next;
}
@Override
public String toString() {
return "Node{" +
"data=" + data +
", next=" + next +
'}';
}
}
SuperLinked类
package com.afternoon.dianlianbiao;
public class SuperLinked {
// 链表的长度
private int size;
// 链表的第一个结点
private Node first;
// 链表的最后一个结点
private Node last;
// 无参构造器
public SuperLinked() {
}
// 把数组添加到链表的尾部
public boolean add(Integer data) {
// 把传入的数据构建成一个结点
Node node = new Node(data, null);
// 如果现在链表是空的,那我就是第一个结点
if (first == null) {
first = node;
} else {
// 如果链表不是空,那我就是最后一个结点
// 我应该是在原来的last结点后面
// 我是原来last结点的下一个结点
last.setNext(node);
}
last = node;
size++;
return true;
}
//在指定位置添加元素
public boolean add(int index, Integer data) {
Node node = getNode(index);
Node newNode = new Node(data, null);
if (node != null) {
Node next = node.getNext();
newNode.setNext(next);
node.setNext(newNode);
} else {
//如果要插入的位置是null,只有一种情况,就是整个链表是null
first = newNode;
last = newNode;
}
size++;
return true;
}
//默认删除头部的数据
public boolean removeFirst() {
if (size < 0) {
return false;
}
if (first != null) {
first = first.getNext();
size--;
}
return true;
}
//删除尾部的数据
public boolean removeLast() {
if (size < 0) {
return false;
}
if (size ==1) {
first = null;
last = null;
size--;
return true;
}
if (last != null) {
last = getNode(size - 2);
last.setNext(null);
size--;
}
return true;
}
//删除指定位置
public boolean remove(int index){
if (size<0){
return false;
}
if (size == 1){
first = null;
last = null;
size--;
return true;
}else{
Node node = getNode(index-1);
node.setNext(node.getNext().getNext());
size--;
}
return true;
}
//修改
public boolean set (int index,Integer data){
Node node = getNode(index);
node.setData(data);
return true;
}
//获取链表的长度
//获取
public Node getNode(int index) {
if (index < 0) {
index = 0;
}
if (index >= size - 1) {
index = size - 1;
}
// 找到第index个
Node cursor = first;
for (int i = 0; i < index; i++) {
cursor = cursor.getNext();
}
return cursor;
}
}
测试类
package com.afternoon.dianlianbiao;
public class Demo {
public static void main(String[] args) {
SuperLinked superLinked = new SuperLinked();
superLinked.add(1);
superLinked.add(2);
superLinked.add(3);
superLinked.add(4);
superLinked.add(5);
superLinked.add(100);
//superLinked.removeFirst();
//superLinked.removeLast();
superLinked.remove(1);
System.out.println(superLinked.getNode(1));
}
}
考试错题
- 如下是一个Java源文件Child.java,编译并运行Child.java,以下结果正确的是(D )(选择一项)
public class Parent1 {
Parent1(String s){
System.out.println(s);
}
}
public class Parent2 extends Parent1{
Parent2(){
System.out.println("parent2");
}
}
public class Child extends Parent2{
public static void main(String[] args) {
Child child = new Child();
}
}
A:正确运行,没有输出值
B:正确运行,输出结果为:parent2
C:编译错误:没有找到构造器Child()
D:编译错误:没有找到构造器Parent1()
2.对于构造函数,下列叙述不正确的是(A)(选择一项) [单选题]
A 子类不被允许调用父类的构造方法
B 构造方法允许重载
C 子类默认调用父类的无参构造方法
D 在同一个类中定义的重载构造方法可以相互调用
3.下面的代码列出了两个方法,它们相互间是否构成重载?(A)[单选题]
public double changeSize(int size,String name,float pattern){}
public void changeSize(int size,String name)
A 是
B 否
子类拥有父类非 __私有(private)______的属性和方法。
父类构造器不能被__继承___,因此不能被方法重写,
但可以被子类方法调用_。
方法重写中,子类方法的修饰符范围的要求是____大于等于父类方法修饰符_______

浙公网安备 33010602011771号