java提供了一个关键字extends,用这个关键字,可以使一个类与另一个类建立父子关系。
public class B extens A{
}
A类称为父类或者基类,B类称为子类或者派生类。
继承的特点:子类能继承父类的非私有成员(成员变量、成员方法)
继承后对象的创建:子类的对象是由子类、父类共同完成的。
public class A {
public int i;
public void print1(){
System.out.println("===A1===");
}
private int j;
private void print2(){
System.out.println("===A2===");
}
} // 2.定义一个类变量记住类的一个对象
public class B extends A {
public int k;//可以在test包下使用,因为B是A的子类
private int n;//不能被test调用
public void print3() {
System.out.println(i);
print1();
//print2();//报错
}
}
public class test {
public static void main(String[] args) {
B b = new B();
System.out.println(b.i);
System.out.println(b.k);
//System.out.println(b.n);报错
b.print2();//报错
b.print1();
b.print3();
}
}
使用继承可以减少重复代码的编写。
关于继承的注意事项:
(1)权限修饰符
其中,缺省和protected很少用。
(2)Java是单继承的,Java中的类不支持多继承,但是支持多层继承。
object类是所以类的祖先,生成的类默认是object的子类
(3)当子类局的父类中的某个方法不好用,或者无法满足自己的需求,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的方法。重写后,方法的访问,Java会遵循就近原则。
B继承A,A的方法不好,可以在B重新写,但是名字和格式要一样,再调用时就会调用B的方法。
重写时要加上@ Override 可以帮助检查有没有错误。
@Override
public void print2(){
System.out.println("1");
}
(4)子类重写父类方法时,访问权限要大于或等于父类的方法权限。public
(5)重写的方法,返回值类型要一样,或者更小,更小的问题以后再说。
(6)私有方法静态方法不能被重写,会报错。
(7)如果输出一个变量的内容时,输出的不是地址而是内容,说明他的tospring被重写了。
(8)这是就近原则。
public class A {
String name = "lzk3";
public void print1() {
System.out.println("111");
}
}
public class B extends A {
String name = "lzk1";
public void printName(){
String name = "lzk2";
System.out.println(name);//lzk2
System.out.println(this.name);//lzk1
System.out.println(super.name);//lzk3,super是父类的引用
}
}
public class test {
public static void main(String[] args) {
B b = new B();
b.printName();
}
}
对于方法的调用也可以使用super
(9)子类构造器:子类的全部构造器,都会先调用父类的构造器,再执行自己。
class F{
public F(){
System.out.println("F的无参构造器被执行");
}
}
class Z extends F{
public Z(){
System.out.println("Z的无参构造器被执行");
}
public Z(String name){
System.out.println("Z的有参构造器被执行");
}
}
public class test {
public static void main(String[] args) {
Z z = new Z();
Z z1 = new Z("张三");
}
}
执行结果:这是因为子类的无参或者有参构造器的第一行默认都会有一个super();来调用父类的无参构造器。如果父类没有无参构造器,那么必须再子类构造器的第一行手写super(),指定去调用父类的有参构造器。
(10)为什么子类构造器要调用父类构造器,有什么应用场景?
public class test1 {
public static void main(String[] args) {
Teacher t = new Teacher("Tom", 30, "Math");
System.out.println(t.getName() + " is " + t.getAge() + " years old and teaches " + t.getSkill());
}
}
class Teacher extends People{
private String skill;
public Teacher(String name, int age, String skill){
super(name, age);//调用父类的构造函数
this.skill = skill;//初始化自己的属性
}
public String getSkill() {
return skill;
}
public void setSkill(String skill) {
this.skill = skill;
}
}
class People{
private String name;
private int age;
public People(){
}
public People(String name, int age){//构造函数
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
补充知识:this()可以调用兄弟构造器
public class test1 {
public static void main(String[] args) {
Student s1 = new Student("Tom", 18, "xxx");
System.out.println(s1.getName() + " " + s1.getAge() + " " + s1.getSchoolName());
}
}
class Student{
private String name;
private int age;
private String SchoolName;
public Student(String name, int age) {
// this.name = name;
// this.age = age;
// SchoolName = "uuu";//默认值,当没有传入SchoolName时,使用默认值
this(name, age, "uuu");//使用带参数的构造器,这一行代码和上面的注释掉的两行代码等价,他调用的是下面Student(String name, int age, String schoolName)的构造器
}
public Student() {
}
public Student(String name, int age, String schoolName) {
this.name = name;
this.age = age;
SchoolName = schoolName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSchoolName() {
return SchoolName;
}
public void setSchoolName(String schoolName) {
SchoolName = schoolName;
}
}
小知识,this和super不能同时出现,因为这两个都要在第一行,而且调用的也不一样,会起冲突。