1.权限修饰符
被不同权限修饰符修饰的内容其能够被使用的范围是不同的:
本类 | 同包类 | 不同包子类 | 不同包下的其他类 | |
---|---|---|---|---|
私有的private | √ | |||
默认的default | √ | √ | ||
受保护的protected | √ | √ | √ | |
公共的public | √ | √ | √ | √ |
以下几点需要值得注意:
- 一般情况下使用最多的是private以及public;
- 能够修饰类的权限修饰符:public,default(默认省略不写);
- 都是成员修饰符,只能修饰成员,不能修饰局部;
- 不能外部调用一个作用域中的局部内容(局部变量);
在具有子父级继承关系的类具有以下几点需要注意:
- 不同包下的子类,私有的内容能够被继承但不能被使用,因为无权使用。
- 在不同包下的子类中,如果想要使用父类中被protected修饰的成员,需要通过继承关系使用(直接在子类使用有权限的父类成员或通过子类对象使用),不能通过父类对象使用。
//父类
public class Decorate {
public int a;//公共类型变量
protected int b;//受保护的变量
int c;//默认类型的变量
private int d;//私有化的变量
//公共方法
public void functiona(){
System.out.println("public");
}
//受保护的方法
protected void functionb(){
System.out.println("protected");
}
//默认类型方法
void functionc(){
System.out.println("default");
}
//私有化的方法
private void functiond(){
System.out.println("private");
}
}
//同包下的子类
public class Test extends Decorate{
public static void main(String[] args) {
Test test = new Test();
System.out.println(test.a);
test.functiona();
test.functionb();
test.functionc();
//test.functiond(); 父类的私有化方法无法使用
}
public void Test2(){
System.out.println(a);
}
}
2.方法的重写
2.1重写与重载的区别
重载:
- 同一个类;
- 方法名相同;
- 参数列表不同|方法签名不同;
重写:
- 不同的两个类;
- 继承关系|实现关系;
- 方法签名相同(方法名+参数列表)
2.2重写的运用
场景:在子类继承父类后,继承了一些方法,有些功能的实现不满意,可以进行功能的重写(重新实现) 。
使用:子类一旦重写方法,子类对象调用的时候,就会发生就近原则;子类对象调用功能时子类存在找子类,子类中没有找父类。
注意:子类一旦重写父类中的方法,就是对父类当中方法屏蔽。
检查是否为重写方法的工具:
- @override强制检查是否存在重写
- 工具中方法的左侧有提示
满足重写的情况:
- ==:方法签名完全相等
- <=:返回值类型为基本数据类型则完全相等,引用数据类型,子类方法返回值类型<=父类返回值类型
- ’>=权限修饰符,子类方法修饰符>=父类方法权限修饰符
不能被重写的方法:
- 被private关键字修饰的方法不能被重写
- 被final关键字修饰的方法不能被重写
- 被static关键字修饰的方法不能被重写,当子类出现与父类静态方法同名的方法时,子类的同名方法也是静态,否则会报错,且不属于方法重写
//测试类
public class Test {
public static void main(String[] args) {
Son son = new Son();
son.talk();
son.name="子类";
son.work();
}
}
//租父类
public class GrandF {
public void work(){
}
}
//父类 继承租父类
public class Fa extends GrandF{
public String name;
public int age;
public void talk(){
System.out.println("父类");
}
public void sleep(){
System.out.println("休息");
}
}
//子类 继承父类
public class Son extends Fa{
public void talk(){
System.out.println("方法重写子类");
}
@Override//方法重写
public void sleep(){
System.out.println("休息2");
}
}
3.多态
3.1多态的体现
多态即一种事物的多种表现形式|多种形态。
多态的最终体现:父类的引用指向子类的对象。
多态的前提:继承|实现
多态的优点:多态可以让程序变得更加灵活,便于后期维护。
3.2多态的使用
当父类类型的引用调用成员时:
成员变量:编译运行看父类|左边|类型
成员方法:编译看父类|左边|类型
运行找子类|右边|类型
注:当通过父类的引用调用成员方法时,如果子类有重写方法就调用重写,没有就调用父类,如果多态不配合方法重写,多态就没有意义。
//测试类
public class TestDuotai {
public static void main(String[] args) {
Father fa = new Son();//父类引用指向子类对象
System.out.println(fa.name);
fa.talk();
}
}
//父类
class Father {
String name = "father";
public void talk(){
System.out.println("这是父类");
}
}
//子类
class Son extends Father{
String name = "son";
//多态如果不配合方法的重写就没有意义
public void talk(){
System.out.println("这是子类");
}
}
4.引用类的转型
引用数据类型的类型提升与基本数据类型的类型转换相似。
向上转型:即自动类型提升
父类类型 引用 = new 子类类型();
向下转型:强制类型转换
从大到小——>从父类到子类
小范围类型 变量 = (小范围类型)大范围类型的数据;
在向下转型过程中可能遇到类型转换异常:
引用instanceof:判断前面的引用是否指向后面类的对象,或者后面类型子类的对象,如果是返回true,如果不是返回false。
值得注意的是:多态引用不能调用子类中独有的方法,需要向下转型。
//测试类
public class CastTest {
public static void main(String[] args) {
Fu fu = new Son();//多态
Bro bro = new Bro();
if(fu instanceof Fu){//判断fu引用是否是Fu类型的对象
System.out.println("true");
}else{
System.out.println("false");
}
}
}
//父类
class Fu{
public void teach(){
System.out.println("教育");
}
public void study(){
System.out.println("学习");
}
}
//子类
class Son extends Fu {
public void play(){
System.out.println("玩");
}
}
//兄弟类 继承了父类
class Bro extends Fu{
public void search(){
System.out.println("调查");
}
}
5.Object类
Object类是java中所有类的父类,所有的类都会直接或间接的继承自Object类,如果没有显示的继承自某个类,默认会继承Object。
5.1equals方法
equals是比较两个对象是否相等,如果想要实现比较对象内容,而非地址值,需要在子类中重写equals方法,需要自己实现比较内容(成员属性的值)。
如果想要实现比较对象内容,而非地址,需要在子类中重写equals方法。
Object类中,equals的默认方法:
public boolean equals(Object obj) {
return (this == obj);
}
==与equals的差别:
==:比较基本数据类型,比较数据值;比较引用数据类型时是比较两个对象的地址是否相等
重写的equals可以比较两个引用数据类型对象的值。
注:通过java实现功能就是为了处理生活中的业务,会以生活中具体的逻辑考虑问题,认为两个对象,如果所有成员属性的值都想等,就应该是一个对象,在java中只要通过new关键字创建的对象,无论成员属性值是否相等,地址都不相等,如果比较地址,都不相等,所以引用数据类型对象的时候,不让它默认比较地址,手动让她比较内容。
//测试类
public class OverrideEquals {
//主方法
public static void main(String[] args) {
Person p1 = new Person("小白",18,150);
Person p2 = new Person("小白",18,150);
//调用重写的equals方法
System.out.println(p1.equals(p2));
}
}
//人类
class Person{
//成员变量
public String name;
public int age;
public int id;
public Person(){
}
//有参构造
public Person(String name,int age,int id){
this.name = name;
this.age = age;
this.id = id;
}
//成员方法
public void getInfo(){
System.out.println("姓名:"+this.name+",年龄:"+this.age+",身份证号:"+id);
}
//人类中对equals重写
public boolean equals(Object obj) {
int num1 = this.id;
if(obj instanceof Person){
Person pp = (Person) obj;
if(pp.id == num1){
return true;
}
}
return false;
}
}
5.2toString方法
- toString以字符串的形式表示当前对象;
- Object类中的toString默认返回当前对象类型的包名.类名@十六进制的地址值;
- 如果想要打印对象的成员变量的值不想打印对象地址,可以在子类中对toString方法进行重写;
注意:
- 当打印一个对象的引用的时候,默认会调用toString,打印的是当前对象调用了toString之后的返回值;
- 以后所定义的javabean,规范: 都会默认提供一个toString以及equals的重写;
public class ToStringDemo02 {
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
s1.name = "zhangsan";
s1.age = 19;
System.out.println(s1);
System.out.println(s1.toString());
}
}
class Student{
public String name;
public int age;
//需求:打印对象引用时候,输出当前对象的所有成员变量的值
public String toString(){
return name+"-->"+age;
}
}
6.abstract抽象方法
抽象方法:被abstract修饰的方法,在抽象方法中可以没有方法体,但是必须存在于抽象类中。
抽象类:被abstract修饰的类。
注:1.抽象类不能够实例化
2.抽象方法必须存在抽象类中
3.抽象类中可以存在抽象方法,可以存在普通的具体方法,可以存在成员,构造器…
4.抽象方法必须要被重写才能使用
5.抽象方法只要被重写就可以使用,不需要再次重写,可以根据需求进行重写
6.抽象类使用: 通过具体子类的对象调用
1.普通的子类: 需要重写所有抽象方法+按需新增
2.抽象子类: 按需重写抽象方法+按需新增
7.abstract不能与private,static,final,native同时存在
抽象类的使用:通过具体子类的对象调用
普通子类需要重写所有抽象方法+按需新增
抽象子类按需重写,按需新增。
abstract不能与private、static、final、native同时存在
public class AbsTest {
public static void main(String[] args) {
//抽象类不能实例化
//Develop de = new Develop();
//具体子类的使用
Java java = new Java();
java.work1();
java.work2();
java.xingxiang();
java.sleep();
Web2 web = new Web2();
web.test();
web.work2();
web.sleep();
web.work1();
//抽象类的多态 : 向上转型
//只能调用develop类中的功能
Develop d = new Java();
d = new Web2();
}
}
public class Java extends Develop{
//对父类中继承的抽象方法进行重写实现
@Override
public void work1() {
System.out.println("JAVA按照规矩办事!!!");
}
@Override
public void work2() {
System.out.println("JAVA做后端开发...");
}
//形象 -->新增方法
public void xingxiang(){
System.out.println("没头发了!!!!又该植发了!!!!!");
}
}