一种类与类之间的关系
使用已存在的类的定义作为基础建立新类
新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类
子类只能继承一个父类
package com.imooc.animal;
public class Animal {
private String name;//昵称
private int month;//月份
private String species;//品种
public Animal() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public String getSpecies() {
return species;
}
public void setSpecies(String species) {
this.species = species;
}
//吃东西
public void eat() {
System.out.print(this.getName()+"吃东西");
}
}
package com.imooc.animal;
public class Cat extends Animal{
private double weight;//体重
public Cat() {
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
//跑动的方法
public void run() {
//子类可以访问父类非私有成员
System.out.print(this.getName()+"是一只"+this.getSpecies()+",它在快乐地奔跑");
}
}
package com.imooc.animal;
public class Dog extends Animal {
private String sex; //性别
public Dog() {
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
//睡觉的方法
public void sleep() {
System.out.println(this.getName()+"现在"+this.getMonth()+"月大"+",正在睡觉");
}
/*
* 方法重载:
* 1.同一个类中
* 2.方法名相同,参数列表不同(参数顺序、个数、类型)
* 3.方法返回值、访问修饰符任意
* 4.与方法的参数名无关
private String sleep(String name) {
return "";
}
public void sleep(String name,int month) {
}
public void sleep(int month,String name) {
}
* */
}
import com.imooc.animal.Animal;
import com.imooc.animal.Cat;
import com.imooc.animal.Dog;
public class Test {
public static void main(String[] args) {
Cat one=new Cat();
one.setName("花花");
one.setSpecies("中华田园猫");
one.eat();
one.run();
Dog two=new Dog();
two.setName("妞妞");
two.setMonth(1);
two.eat();
two.sleep();
//父类不可以访问子类特有成员,即便它是公有的
Animal three=new Animal();
//three.run();//报错
}
}
复制代码
方法重写
语法规则:
在子类中定义
方法名和参数类型、顺序、个数(不包括参数名)都要与父类继承的方法相同
public void eat(String name) {
System.out.println(name+"在吃东西");
}
public void jump() {
System.out.println("跳跃是一种本能");
}
/*
* 方法重写:
* 1.有继承关系的子类中
* 2.方法名相同,参数列表相同(参数顺序、个数、类型)
* 3.与方法的参数名无关
* 4.方法的返回值和访问修饰符是可以允许有变化的
*/
//当子类重写父类方法后,子类对象调用的是重写后的方法
public void eat() {
System.out.println(this.getName()+"最近没有食欲");
}
public void eat(String month) {
System.out.println(month+"最近没有食欲");
}
/*报错:与父类中的jump方法不兼容
* 返回值为void或者基本数据类型,要求父子完全一致
* 返回值为引用类型时,可以是父类或其子类
public int jump() {
System.out.println("狗狗是助跑式跳跃");
return 1;
}
*/
复制代码
在子类中可以定义与父类当中重名的属性,优先执行子类当中的赋值
访问修饰符
公有的:public:允许在任意位置访问
私有的:private:只允许在本类中进行访问
受保护的:protected:允许在当前类、同包子类/非子类、跨包子类调用;跨包非子类不允许
默认:允许在当前类、同包子类/非子类调用;跨包子类/非子类不允许调用
访问修饰符对方法重写的影响
访问修饰符的访问范围需要大于等于父类的访问范围
super关键字的使用
super:父类对象的引用
super.eat();
super.x=4;
复制代码
tip:父类的构造方法不允许被继承、不允许被重写,但是会影响子类对象的实例化
子类的构造的过程中必须调用其父类的构造方法
如果子类的构造方法中没有显式标注,则系统默认调用父类无参构造方法
如果子类构造方法中既没有显式标注,且父类中没有无参的构造方法,则编译一定出错
Implicit super constructor Parent1() is undefined. Must explicitly invoke another constructor
隐式的父类无参构造方法未找到,必须显式地调用另外的构造方法
使用super()可以指定父类构造方法,super()必须放在子类构造方法有效代码第一行
super();
super(String name,int month);
this和super都不能在静态方法中调用,两者在调用构造方法时不能共存
继承后的初始化顺序
类的加载:父类静态成员--子类静态成员--子类对象实例化(父类对象构造,包括属性、构造代码块、构造方法--子类对象构造)
访问修饰符不影响静态成员加载顺序,跟书写位置有关
Object类
Object类是所有类的父类
一个类没有使用extends关键字明确标识继承关系,则默认继承Object类(包括数组)
Java中的每个类都可以使用Object中定义的方法
子类中方法可以不经过重写,直接重载父类的方法
例如equals()方法(等效于==),当继承Object中的equals方法时,比较的是两个引用是否指向同一个对象,即是否指向同一片内存空间,子类可以通过重写equals方法的形式,改变比较的内容
Animal one=new Animal("花花",2);
Animal two=new Animal("花花",2);
boolean flag=one.equals(two);
System.out.println("one 和 two的引用比较"+flag);
System.out.println("one 和 two的引用比较"+(one==two));
String str1=new String("hello");
String str2=new String("hello");
flag=str1.equals(str2);
System.out.println("str1 和 str2的引用比较"+flag);
System.out.println("str1 和 str2的引用比较"+(str1==str2));
public boolean equals(Object obj) {
if(obj==null) {
return false;
}
//强制转换为Animal类型
Animal temp=(Animal)obj;
//字符串用equals()比较,int型数据用==比较
if(this.getName().equals(temp.getName())&&(this.getMonth()==temp.getMonth())) {
return true;
}else {
return false;
}
}
//方法重载
public boolean equals(Animal obj) {
if(obj==null) {
return false;
}
if(this.getName().equals(obj.getName())&&(this.getMonth()==obj.getMonth())) {
return true;
}else {
return false;
}
}
复制代码
if语句中,可以两个都用equals或者两个都用==进行比较吗?
由于通过Animal类型参数重载了equals(),所以代码运行时自动定位类型匹配方法
//重写toString()方法
public String toString() {
return "昵称:"+this.getName()+";年龄:"+this.getMonth();
}
/*toString测试:
* 1.输出对象名时,默认会直接调用类中的toString方法
* 2.继承Object中的toString方法时,输出对象的字符串表示形式:类型信息+@+地址信息
* 3.子类可以通过重写toString方法的形式,改变输出的内容以及表现形式
*/
System.out.println(one.toString());
System.out.println(one);
System.out.println(str1);
复制代码
==比较的是变量里存储的值,对于基本数据类型,变量里存储的是数值,==比较的是数值是否相等;对于引用数据类型(例如String、自定义类等),变量里存的是对象的内存地址,==默认比较的是是否指向同一内存空间,也就是地址是否相同。
final
final class:该类没有子类,不允许被继承 可写成public final class或final public class
不允许子类重写,在方法的返回值前加final,同时可以被子类正常继承使用,不能修饰构造方法
变量分为以下两类:
final 方法内局部变量:只要在具体被使用之前进行赋值即可,一旦赋值不允许被修改
final 类当中的成员属性:赋值过程:1.定义直接初始化 2.构造方法 3. 构造代码块
不赋值系统会报错
提示菜单快捷键:alt+/ 可以快速生成重写方法模板
final 引用数据类型 实例化后不允许再进行引用地址的修订,但属性值仍可更改
static+final 表示全局不允许修订的内容(方法和变量),如配置信息
注解
可以声明在包、类、属性、方法、局部变量、方法参数等的前面,用来对这些元素进行说明、注释
按照运行机制可以分为:源码注解(@Override)、编译时注解(@NotNull)、运行时注解(甚至会影响到运行逻辑@Autowired)
在当前阶段保留,在进行下一阶段时会被丢弃
按照来源分:来自JDK的注解(@Override)、来自第三方的注解(@Autowired)、我们自己定义的注解
元注解
定义注解的注解,对注解进行标注
父类的静态方法无法被重写
public static Animal create(){
return new Animal();
}
public static Dog create(){
return new Dog();
}
复制代码
不会报错的原因是:系统认为create是Dog类专属的一个方法,与父类无关,更不是方法重写