在保持原有类特性的基础上进行扩展,增加新功能,从而产生新的类,继承主要解决的问题是对共性的抽取,优点是可以实现代码复用
class A extends B{
}
其中:A是子类,也叫派生类;B是父类,也叫基类、超类
class Animal {
public String name;
public int age;
public void eat(){
System.out.println(this.name + "正在吃");
}
}
class Dog extends Animal {
public void swim(){
System.out.println(this.name + "正在游泳");
}
}
class Bird extends Animal {
public String wing;//翅膀
public void fly() {
System.out.println(this.name + "正在飞");
}
}
public class TextDame1 {
public static void main(String[] args) {
Animal animal = new Animal();
animal.name = "可可";
animal.eat();
Dog dog = new Dog();
dog.name = "小小";//继承了父类的成员变量
dog.swim();
dog.eat();//继承了父类的方法
Bird bird = new Bird();
bird.name = "大大";
bird.fly();
}
}
子类会将父类中的成员变量或者成员方法继承到子类中;子类继承父类之后,要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承
(1) 子类和父类不存在同名成员变量
class A {
public int a;
public int b;
}
class B extends A {
public int c;
public void method(){
a = 10;//访问从父类继承的
b = 20;
c = 30;//访问子类自己的
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
public class TextDame2 {
public static void main(String[] args) {
B b = new B();
b.method();
}
//结果:
// 10
// 20
// 30
}
(2)子类和父类存在同名成员变量时,优先访问子类自己的,自己没有才会访问父类的
class A {
public int a;
public int b;
}
class B extends A {
public boolean b;
public int c;
public void method(){
a = 10;//访问从父类继承的
b = false;//同名是优先访问子类自己的
//b = 10;//会报错,因为是优先访问子类自己的,而子类的b的类型是Boolean,而不是整形
c = 30;//访问子类自己的
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
public class TextDame2 {
public static void main(String[] args) {
B b = new B();
b.method();
}
//结果:
// 10
// false
// 30
}
(1)子类和父类不存在同名成员方法
class A {
public int a;
public int b;
public void funcA(){
System.out.println("父类的funcA()方法");
}
}
class B extends A {
public void funcB(){
System.out.println("子类的funcB()方法");
}
public void method(){
funcA();//调用父类的成员方法
funcB();//调用子类自己的成员方法
}
}
public class TextDame2 {
public static void main(String[] args) {
B b = new B();
b.method();
}
//结果:
//父类的funcA()方法
//子类的funcB()方法
}
(2)子类和父类存在同名成员方法时,优先访问子类的成员方法,子类没有才到父类去找
class A {
public void func(){
System.out.println("父类的fun()方法");
}
}
class B extends A {
public void func(){
System.out.println("子类的func()方法");
}
public void method(){
func();
}
}
public class TextDame2 {
public static void main(String[] args) {
B b = new B();
b.method();
}
//结果:
// 子类的func()方法
}
super不能使用在静态方法中,super
class A {
public int a;
}
class B extends A {
public int a;
public void method(){
super.a = 10;//此时的a就是访问的父类的成员便量,但是不加super,默认就是子类自己的a
a = 20;//等价于this.a = 20
System.out.println(super.a);//10
System.out.println(a);//20
}
}
public class TextDame2 {
public static void main(String[] args) {
B b = new B();
b.method();
}
}
class A {
public void func(){
System.out.println("父类的fun()方法");
}
}
class B extends A {
public void func(){
System.out.println("子类的func()方法");
}
public void method(){
super.func();//访问父类的func方法
func();//访问子类的func方法,等价于this.func()
}
}
public class TextDame2 {
public static void main(String[] args) {
B b = new B();
b.method();
}
//结果:
// 父类的fun()方法
// 子类的func()方法
}
子类继承了父类以后必须先帮助父类进行构造,帮助父类进行构造就是显示调用父类的构造方法,这里此时构造的意义就是分配内存,初始化从父类继承过拉里的父类成员
class A {
public int a;
public int b;
public A(){
System.out.println("父类不带参数的构造方法");
}
}
class B extends A {
public int c;
public B(){
super();//当父类只有一个不带参数的构造方法的时候,子类默认会有super(),帮助父类进行构造
System.out.println("子类不带参数的构造方法");
}
}
public class TextDame2 {
public static void main(String[] args) {
B b = new B();
}
//结果:
// 父类不带参数的构造方法
// 子类不带参数的构造方法
}
class A {
public int a;
public int b;
public A(int a, int b) {
this.a = a;
this.b = b;
}
}
class B extends A {
public int c;
//不加这个构造方法会报错,是因为,子类继承了父类以后必须先帮助父类进行构造
public B(){
super(30,20);
System.out.println("B不带参数的构造方法");
}
}
public class TextDame2 {
public static void main(String[] args) {
B b = new B();
}
}
(1)都是java的关键字
(2)都只能在非静态方法中调用,用来访问非静态成员方法和变量
(3)在构造方法中调用,都必须放在构造方法的第一条,且不能同时存在
(1)this是当前对象的引用,即当前实例方法的对象的引用;super是子类对象从父类继承过来的成员的引用
(2)在非静态成员方法中,this用来访问本类的方法和属性;super用来访问父类继承下来的方法和属性
(3)this是非静态成员方法的一个隐藏参数;super不是隐藏的参数
(4)成员方法中直接访问本类成员时,编译之后会将this还原,即本类非静态成员都是通过this来访问的;在子类中如果通过super访问父类成员,编译之后在字节码层面super实际是不存在的
(5) 在构造方法中,this(…)用于调用本类构造方法;super(…)用于调用父类构造方法,两种调用不能同时在构造方法中出现
(6)构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有
class A {
public int a;
public int b;
public A(){
System.out.println("父类不带参数的构造方法");
}
public A(int a, int b) {
this();//调用本类的不带参数的构造方法,这个不写就没有
this.a = a;
this.b = b;
System.out.println("父类带两个参数的构造方法");
}
}
class B extends A {
public int c;
public B(){
//super();//调用父类的不带参数的构造方法,这个不写编译器会自动加上
super(23,2);//调用父类的带两个参数的构造方法
System.out.println("父类不带参数的构造方法");
}
}
public class TextDame2 {
public static void main(String[] args) {
B b = new B();
}
//结果:
// 父类不带参数的构造方法
// 父类带两个参数的构造方法
// 父类不带参数的构造方法
}
(1)父类静态代码块优先于子类静态代码块执行,且是最早执行
(2)父类实例代码块和父类构造方法紧接着执行
(3)子类的实例代码块和子类构造方法紧接着再执行
(4)第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行(静态的只有一份)
class Animal {
public String name;
public int age;
static {
System.out.println("Animal的静态代码块");
}
{
System.out.println("Animal的实例代码块");
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Animal带有两个参数的构造方法");
}
}
class Dog extends Animal {
static {
System.out.println("Dog的静态代码块");
}
{
System.out.println("Dog的实例代码块");
}
public Dog() {
super("小小", 2);
System.out.println("Dog不带参数的构造方法");
}
}
public class TextDame1 {
public static void main(String[] args) {
Dog dog1 = new Dog();
System.out.println("============");
Dog dog2 = new Dog();
}
//结果:
// Animal的静态代码块
// Dog的静态代码块
// Animal的实例代码块
// Animal带有两个参数的构造方法
// Dog的实例代码块
// Dog不带参数的构造方法
// ============
// Animal的实例代码块
// Animal带有两个参数的构造方法
// Dog的实例代码块
// Dog不带参数的构造方法
}
package extendsText;
public class TextDame2 {
public int a = 10;
protected int b = 20;
int c = 30;
private int d = 40;
public static void main(String[] args) {
TextDame2 textDame2 = new TextDame2();
System.out.println("同一包中的同一类:" + textDame2.a);
System.out.println("同一包中的同一类:" + textDame2.b);
System.out.println("同一包中的同一类:" + textDame2.c);
System.out.println("同一包中的同一类:" + textDame2.d);
}
//结果:
// 同一包中的同一类:10
// 同一包中的同一类:20
// 同一包中的同一类:30
// 同一包中的同一类:40
}
package extendText;
public class TextDame2 {
public int a = 10;
protected int b = 20;
int c = 30;
private int d = 40;
}
package extendText;
public class TextDame1 {
public static void main(String[] args) {
TextDame2 textDame2 = new TextDame2();
System.out.println("同一包中的不同类:" + textDame2.a);
System.out.println("同一包中的不同类:" + textDame2.b);
System.out.println("同一包中的不同类:" + textDame2.c);
// System.out.println("同一包中的不同类:" + textDame2.d);报错,被private修饰的只能在当前类被访问,不同类中使不能访问的
}
//结果:
// 同一包中的不同类:10
// 同一包中的不同类:20
// 同一包中的不同类:30
}
package extendText;
public class TextDame2 {
public int a = 10;
protected int b = 20;
int c = 30;
private int d = 40;
}
package childText;
import extendText.TextDame2;
public class TextDame3 extends TextDame2 {
public void method(){
super.a = 50;
super.b = 60;
// super.c = 70;报错,没有写就就是包访问权限,只能在同一个包中访问
// super.d = 80;报错,被private修饰的只能在当前类被访问
}
}
package extendText;
public class TextDame2 {
public int a = 10;
protected int b = 20;
int c = 30;
private int d = 40;
}
package childText;
import extendText.TextDame2;
public class TextDame4 {
public static void main(String[] args) {
TextDame2 textDame2 = new TextDame2();
System.out.println("不一包中的非子类:" + textDame2.a);
// System.out.println("不一包中的非子类:" + textDame2.b);报错,protected修饰的再不同包中的非子类是不能被访问到的
// System.out.println("不一包中的非子类:" + textDame2.c);报错,没有写就就是包访问权限,只能在同一个包中访问
// System.out.println("不一包中的非子类:" + textDame2.d);报错,被private修饰的只能在当前类被访问
}
}
(1)单继承
(2)多层继承
(3)不同类继承同一个类
(4)java不支持多继承
表示该字段或变量为常量
public class TextDame1 {
public static void main(String[] args) {
final int a = 10;
// a = 20;报错,a被final修饰就是常量了,不能被修改
}
}
该类不能被继承
final class A {
}
//报错,被final修饰的类不能被继承
//class B extends A{
//
//}
该方法不能被重写
class A {
public final void func(){
System.out.println();
}
}
class B extends A{
// 被final修饰的方法不能被重写
// @Override
// public void func() {
//
// }
}
(1)继承是is-a的关系
(2)组合是has-a的关系,和继承类似,组合也是一种表达类之间关系的方式,也是能够达到代码重用的效果,组合仅仅是将一个类的实例作为另外一个类的字段
class A{
}
class B{
}
//组合
class C{
private A a;
private B b;
}