@16:继承
继承最大的好处就是:提高代码的复用性。
Person:属性:age,name,height -----> 这些属性都是private修饰的,被封装好的。
方法:eat( ),sleep()
Student:属性:sno
方法:study( )
Student 继承自Person , 那么Student里面就有:age,name,height ,sno,eat( ),sleep(),study( )
注意:
1:父类中private修饰的属性,其实子类也是继承过来的,只是由于封装的特性,不可以在子类中直接的调用,但是可以通过setter getter接口间接调用。
2:一个父类可以有无数的子类,但是一个子类只能有一个直接父类,但是他可以间接的继承自其他的父类,比如说当其他的孙子类或是重孙子类。
3:所有的类都直接或者间接的继承自Object。
继承的内存分析:(下面连接)
https://blog.csdn.net/TYRA9/article/details/128729074?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167955107816782425164761%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=167955107816782425164761&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-1-128729074-null-null.142
还需要注意的是:父类中的static修饰的成员变量与成员方法也会被继承到子类中,但是不可以在子类中重写
这些方法,因此不能实现多态。
如果父类的属性被声明为 public 或 protected,那么子类可以继承这些属性,并且可以在子类中访问这些属性。如果父类的属性被声明为 private,那么子类也会继承这些属性,但由于封装的特性,子类无法直接调用。如果父类的属性没有被声明为任何访问限定符修饰符,即使用 default 修饰符,则同包的子类可以继承这些属性,但不同包的子类无法继承这些属性。
需要注意的是,如果父类的属性被声明为 final,那么子类无法覆盖这些属性(常量被放到常量池中),但是子类仍然可以继承这些属性。如果父类的属性被声明为 static,那么子类可以继承这些属性,可以通过子类的实例,子类类名,父类类名访问这些属性。
@17:protected关键字
protected关键字最大权限到不同包的子类。
类修饰符:public,default
方法/属性修饰符:public,protected,default,private
@18:方法的重写
方法的重写:发生在继承中,子类与父类之间,当子类对父类提供的方法不满意的时候,子类对父类提供的方法进行重写。
重载与重写的区别:
重载:发生在同一个类中,重载的方法的方法名相同,参数不同。
重写:子类与父类之间,当子类对父类提供的方法不满意的时候,子类对父类提供的方法进行重写。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YOVJJz0S-1679579269434)(D:/%E4%BD%A0%E5%A5%BDJava/1007.png)]
注意:重写的返回值:当父类与子类的返回值都是基本数据类型的时候(比如说父类返回值类型是int,子类的返回值类型是double)是不可以的,当父类与子类的返回值类型是引用类型时,必须满足父类的返回值范围大于子类才行(比如说父类返回Person类型,子类返回Student类型,person是Student的父类,这样是可以的)。
内存图:
看这个图之前最好看一下继承中的内存分析
@19:super关键字
看这个之前最好看一下继承中的内存分析
public class M1 {
int age = 10;
String name = "000";
double height = 199.2;
public void eat() {
}
}
public class M2 extends M1{
int oop = 100000;
public void said() {
this.age = 100;
}
public void see() {
System.out.println(this.age); // 100
System.out.println(super.age); // 100
System.out.println(super.height);
this.oop = 19;
System.out.println(this.oop);
}
}
public class M3 extends M2{
public void sleep() {
this.age = 1000;
System.out.println(this.age); // 1000
System.out.println(super.age); // 1000
System.out.println(this.oop);
System.out.println(super.oop);
this.see();
}
public static void main(String[] args) {
M2 m2 = new M2();
m2.said();
m2.see();
M3 m3 = new M3();
m3.sleep();
}
}
/*
100
100
199.2
19
1000
1000
100000
100000
1000
1000
199.2
19
*/
继承条件下构造方法的执行过程
用链表实现队列和栈的功能
package Novice_class;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
// 单链表实现队列和栈
public class LinkedListToQueueAndStack {
public static class Node<V> {
public V value;
Node<V> next;
public Node(V value) {
this.value = value;
}
}
public static class MyQueue<V> {
Node<V> head;
Node<V> tail;
int usedSized;
public MyQueue() {
head = null;
tail = null;
usedSized = 0;
}
public boolean isEmpty() {
return this.usedSized == 0;
}
public int size() {
return usedSized;
}
public void offer(V value) {
Node<V> cur = new Node<>(value);
if(head == null) {
head = cur;
tail = cur;
}else {
tail.next = cur;
tail = cur;
}
tail.next = null;
usedSized++;
}
public V poll() {
if(this.isEmpty()) {
return null;
}
V cur = head.value;
head = head.next;
if(head == null) {
tail = null;
}
usedSized--;
return cur;
}
public V peek() {
return this.isEmpty() ? null : this.head.value;
}
}
public static class MyStack<V> {
Node<V> head;
Node<V> tail;
int usedSize;
public MyStack() {
this.head = null;
this.tail = null;
this.usedSize = 0;
}
public Boolean isEmpty() {
return this.usedSize == 0;
}
public int size() {
return this.usedSize;
}
public void push(V value) {
Node<V> cur = new Node<>(value);
if(head == null) {
head = cur;
tail = cur;
}else {
tail.next = cur;
tail = cur;
}
tail.next = null;
usedSize++;
}
public V pop() {
if(head == null) {
return null;
}
if(head == tail) {
V value = this.head.value;
head = null;
tail = null;
usedSize--;
return value;
}
Node<V> cur = head;
while(cur.next != tail) {
cur = cur.next;
}
V value = this.tail.value;
tail = cur;
tail.next = null;
usedSize--;
return value;
}
public V peek() {
return this.isEmpty() ? null : this.tail.value;
}
}
public static void testStack() {
MyStack<Integer> myStack = new MyStack<>();
Stack<Integer> test = new Stack<>();
int testTime = 5000000;
int maxValue = 200000000;
System.out.println("测试开始!");
for (int i = 0; i < testTime; i++) {
if (myStack.isEmpty() != test.isEmpty()) {
System.out.println("isempty Oops!");
}
if (myStack.size() != test.size()) {
System.out.println("size Oops!");
}
double decide = Math.random();
if (decide < 0.33) {
int num = (int) (Math.random() * maxValue);
myStack.push(num);
test.push(num);
} else if (decide < 0.66) {
if (!myStack.isEmpty()) {
int num1 = myStack.pop();
int num2 = test.pop();
if (num1 != num2) {
System.out.println("pop Oops!");
}
}
} else {
if (!myStack.isEmpty()) {
int num1 = myStack.peek();
int num2 = test.peek();
if (num1 != num2) {
System.out.println("isempty Oops!");
}
}
}
}
if (myStack.size() != test.size()) {
System.out.println("size Oops!");
}
while (!myStack.isEmpty()) {
int num1 = myStack.pop();
int num2 = test.pop();
if (num1 != num2) {
System.out.println("isempty Oops!");
}
}
System.out.println("测试结束!");
}
public static void main(String[] args) {
//testQueue();
testStack();
}
}