1.继承
继承是类与类的一种关系;Java中的继承是单继承,只有一个父类。
继承的好处:子类直接拥有父亲的所有属性和方法(private修饰的无效!),可实现代码复用。
语法规则:
class 子类 extends 父类
eg:class Dog extends Animal{
…
}
2.Java中的方法重写
如果子类对继承父类的方法不满意,是可以重写父类继承的方法的,当调用方法时会优先调用子类的方法。
语法规则:返回值类型,方法名,参数类型及个数都要与父类继承的方法相同,才叫方法的重写。
3.Java中的继承初始化顺序
a.初始化父类再初始化子类。(使用构造方法可以看出,虽然仅创建了子类的对象,但是先执行了父类的构造方法,之后才执行子类的构造方法)。
b.先执行初始化对象中的属性,再执行构造方法中的初始化。
4.Java中final的使用
final关键字: 表示“最终的”,即不可修改。
final可以修饰类、方法、属性和变量
a.修饰类:该类不允许被继承
b.修饰方法:该方法不允许被重写
c.修饰属性:则该属性不会进行隐式初始化(不会自动初始化,之前我们没有初始化都是系统帮我们自动初始化),需要手动初始化或者在构造方法中初始化 (但二者只能选一,即只能初始化一次后便不能更改)
d.修饰变量,只能在声明的时候赋一次值,成为常量(static final 会使其成为全局常量)。
5.Java中的super的使用
super关键字:在父类的内部使用,可以代表父类对象。
a.访问父类的属性 super.age
b.访问父类的方法 super.eat()
父类对象的属性和子类对象的属性并无关系,是两个属性。
如果想得到子类值:
调用父类的方法:
如果想调用子类的方法,直接输入方法名即可:
子类的构造的过程当中必须调用其父类的构造方法,相当于super();默认是调用无参的,super()是隐式显示的(就是看不见,但是程序里就有这句话)。
如果子类的构造方法中没有显示调用父类的构造方法,系统会默认调用父类无参的构造方法。
如果要显示的调用父类的构造方法,必须在子类的构造方法第一行中添加super()。
如果子类构造方法中既没有显示调用父类的构造方法,而父类又没有无参的构造方法(例如自己定义了一个有参的构造方法,系统就不会帮我们自动生成一个无参的构造方法),则编译出错。如果父类是定义了有参的构造方法,那么子类必须super(父类的参数),或者父类中添加一个无参的构造方法,否则出错,因为默认调用的是super()是无参的。
一个类中没有定义构造方法,则系统会默认为此类定义一个无参的构造方法。如果自定义了一个带参的构造方法,则系统不会为其添加无参的构造方法。
6.Java中的Object类(一)
Object类是所有类的父类,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类默认继承Object类,且Object类中的方法适合所有子类。
toString()方法
在Object类里面定义toString()方法的时候返回的对象的哈希code码(对象地址字符串)
如果我们在代码里面直接输出一个对象,会输出这个对象在内存中的地址,我们把它称为哈希码,哈希码是通过哈希算法生成的一个字符串用来唯一区分对象的。
可以通过重写toString()方法表示出对象的属性
(我们经常在输出对象的时候希望得到子类的属性值,那么我们就要重写从父类继承来的toString()方法,IDEA中右键空白处-generate-生成generate toString(),他就会根据我们对象的属性帮我们生成一个toString()方法来输出属性值)。
有的人可能会有疑问:为什么System.out.println(dog)会直接输出属性值,并没有调用toString方法啊?这是因为当System.out.println(对象)时,默认使用toString()方法,将对象转为字符串输出,toString()方法继承于所有类的隐性基类(所有类的大哥大 Object类),如果某类无重写toString()方法,这时调用toString()将得到(类名+地址名名)这样的字符串。即在写Java代码的时候,当你打印一个对象的时候,实际上是调用对象的toString()方法!这是在类的定义阶段,属性还没有初始化 ,就是打印对象时,打印默认的是 对象.toString(); 可以理解为输出所有的属性值。
7.Java中的Object类(二)
Dog dog = new Dog(),很多人误以为这个dog就是我们创建的对象,其实不然,它仅仅是我们对象在内存中的地址。在操作这个地址的时候,其实等于间接的操作了我们的对象。准确的说,这个dog应该叫做引用,它只是引用了一块内存中的地址。
equals()方法,返回值是布尔类型
比较的是对象的引用是否指向同一块内存地址-对象实例化时,即给对象分配内存空间。
使用方法如:dog.equals(dog2);
如果是两个对象,但想判断两个对象的属性是否相同,则重写equals()方法
同上,也是可以让编译器自动为我们创建一个equals方法。
a.地址是否相同----if (this == obj)
this关键字看这篇:this关键字详解
补充:在同一个类中,对于静态方法,其他的静态或非静态方法都可以直接调用它。
而对于非静态方法,其他的非静态方法是可以直接调用它的。但是其他静态方法只有通过对象才能调用它。
b.对象是否为空----if (obj == null)
c.getClass()可以得到类对象,判断类型是否一样-----if (getClass() != obj.getClass())
new出来的是类的对象,关注的是类的属性的具体的数据;
类对象是类的代码信息,关注的是类有什么属性和方法。
d.强制类型转换,对象类型不相同不能直接比较
e.属性值是否一样----if (age != other.age)
8.Java中的多态
多态: 指的是对象的多种形态
主要分为 引用多态 、方法多态
继承是多态的实现基础,别忘了子父类要有继承关系.
多态特性:
*引用多态
a.父类引用可以指向本类对象 Animal obj1 = new Animal();
b.父类引用可以指向子类对象 Animal obj2 = new Dog();
但是我们不能用子类的引用指向父类对象 Dog obj3 = new Animal();//错
*方法多态
a.在父类Animal中定义一个eat()方法,输出一个语句(动物有吃的能力); 在子类Dog中重写eat()方法,输出一个语句(狗是吃肉的); 那么我们在测试类main函数里面,如果obj1.eat() ,那么调用的是父类的方法。若用obj2调用eat()方法,那么调用的是子类的方法。
b.还有一种情况,比如创建一个继承父类Animal的子类Cat ,但是Cat里并不重写继承的eat()方法。 然后,我们在测试类main函数里创建一个子类对象, Animal obj3 = new Cat(); 然后调用 obj3.eat(); 那么,结果调用的则是子类继承父类的方法(输出结果:动物有吃的能力)。
c.最后一种特殊情况,多态的特性是不能使用的. 若在子类添加一个独有的方法 public void watchDoor() ,含有一句输出语句(狗具有看门的能力); 那么我们在测试类的main函数当中(得先定义好对象Animal obj2 = new Dog() ),就不能用obj2.watchDoor(),即不能通过父类的引用调用子类的方法。
9.多态中的引用类型转换
a.向上类型转换(隐式/自动类型转换),是小类型到大类型的转换。
如:Dog dog=new Dog();Animal animal=dog;//正确,自动类型提升,向上类型转换
b.向下类型转换(强制类型转换),是大类型到小类型的转换(存在风险,溢出)
如:Dog dog1=(Dog)animal;//向下类型转换
c.instanceof运算符,来解决引用对象的类型,避免类型转换的安全性问题。如:
Dog dog=new Dog();
Animal animal=dog;
Cat cat=(Cat)animal;//编译时不会出错(按Cat类型进行编译),但运行时会报错,因为它开辟的是Dog类型的空间,而(无法将引用类型进行转换)无法将dog对象转换成Cat类型,并且此方法对程序的安全性有影响。此时应该利用instanceof和if语句结合使用,进行验证,以保证程序的安全性,如:
10.Java中的抽象类
语法定义:
抽象类前使用abstract关键字修饰,则该类为抽象类。
应用场景:
a、在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法
b、从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为子类的模板,从而避免了子类设计的随意性。
作用:
限制规定子类必须实现某些方法,但不关注实现细节。
使用规则:
a、abstract定义抽象类
b、abstract定义抽象方法,只有声明,不需要实现
c、包含抽象方法的类是抽象类
d、抽象类中可以包含普通的方法,也可以没有抽象方法
e.抽象类不能直接创建,可以定义引用变量
11.Java中的接口
接口=全局常量+公共的抽象方法;
接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部数据,也不关心这些类里方法的实现细节,它只规定这些类里必须提供某些方法。
接口用interface定义,语法:
[修饰符] abstract interface 接口名 [extends 父接口1,父接口2……]
{//中括号中为可选项
零个到多个常量定义……
零个到多个抽象方法的定义
}
接口就是用来被继承、被实现的,修饰符一般建议用public,不能使用private和protected修饰接口。
接口中的属性是常量(public static final修饰),系统会自动加上。
接口中的方法只能是抽象方法(public abstract修饰),系统会自动加上。
使用接口:一个类可以实现一个或多个接口,实现接口使用implements关键字。java中一个类只能继承一个父类,是不够灵活的,通过实现多个接口可以做补充。
继承父类实现接口的语法:
[修饰符] class 类名 extends 父类 implements 接口1,接口2……
{类体部分//如果继承的是抽象类,需要实现继承的抽象方法;要实现接口中的抽象方法
}
如果要继承父类,继承父类必须在实现接口之前。
接口命名时首字母为I,以区分类名。可通过Add选项继承父接口。
这里的abstract有和没有都可以,没有的话系统会帮助我们自动添加,通常来讲我们是不写的。
当我们实现一个接口的时候,就必须实现这个接口里面的方法:
实现时可以利用接口的引用指向实现了接口的对象,调用其方法,如 :
IPlay ip2=new Psp();
ip2.playGame();
接口的使用还经常与匿名内部类配合(匿名内部类就是没有名字的内部类,多用于关注实现而不关注实现类的名称)
语法格式:
Interface i=new Interface(){
public void method(){
System.out.print("匿名内部类实现接口的方式……");
}
};
//即通过创建接口的对象,直接写出实现的方法,再调用此方法
来源:CSDN
作者:sosalt8
链接:https://blog.csdn.net/weixin_43684054/article/details/104487456