面向对象编程(包+继承)
2021/9/10 20:05:03
本文主要是介绍面向对象编程(包+继承),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
文章目录
- 一、包
- 1.包的概述
- 2.使用系统包
- 3.重复包的使用
- 4.导入静态包(不建议)
- 5.常用的系统
- 二、继承(extends)
- 1.继承初理解
- 2.继承的好处
- 3.private修饰参数
- 4.(面试问题)子类继承了父类那些东西?
- 5.super关键字
- 6.代码的执行顺序
- 7.复杂的继承关系
- 8.继承的注意事项
- 9.继承时,相同名属性的分布
- 三、访问修饰限定符
- 四、final:
- 五、组合
- 六、多态
- 1.向上转型
- 2.向下转型
- 3.重写
- 4.理解多态
- 七、抽象类
- 八、接口
- 1.接口的细节
- 2.Comparable接口
- 3.比较器(Comparator)
- 3.Cloneable接口
一、包
1.包的概述
包是组织类的方式,使用包的主要目的是保证类的唯一性。
路径不同,则就是唯一的,例如:同事与你写了一个同样名字的类,就会导致冲突,导致编译无法通过
包其实是一个文件夹
2.使用系统包
1.使用导入包的方式来使用系统包
在java文件夹中有这样一个文件(一般为压缩文件,这是解压后文件),储存着java的源代码中的包
像这种头文件叫做导入包
使用*的时候,导入所有的包(你使用那个包时自动导入)
2.不使用系统包的方式来导入包
例:
使用这种方式来进行导入,标明好路径。
3.重复包的使用
import java.util.*; import java.sql.*;
在这两个包中同时拥有Date这个类,会导致歧义,以至于编译器无法识别,在这种情况下,就不能使用导入系统包的方式来进行,而必须写完整的类名
4.导入静态包(不建议)
import static java.lang.System.*;
这种导入是静态导入导入这种包后,常使用的打印函数就可以这样写
out.println("haha");
5.常用的系统
import java.lang.*;//系统常用的基础类(String、Object),此包从JDK1.1后自动导入。 import java.lang.reflect.*;//反射编程包; import java.net.*;//进行网络编程的开发包 import java.sql.*;//进行数据库编程的开发包 import java.util.*;//是java提供的工具程序包。(集合类等) import java.io.*;//I/O编程开发包。
二、继承(extends)
1.继承初理解
在编写类时,可能会有很多相同的属性及方法。
例:
class dog{ public String name; public int age; public void eat(){ System.out.println("chi()"); } public void crow(){ System.out.println("wangwang"); } } class cat{ public String name; public int age; public void eat(){ System.out.println("chi()"); } public void fly(){ System.out.println("fly()"); } }
这时候就可以使用继承,把相同的属性或方法包装起来,其他类来继承
class animal{ public String name; public int age; public void eat(){ System.out.println("chi()"); } } class dog extends animal{ public void crow(){ System.out.println("wangwang"); } } class bird extends animal{ public void fly(){ System.out.println("fly()"); } }
在上述例子中:
dog类extends了animal
这时
dog:子类 、 派生类
animal:父类、基类、超类
2.继承的好处
可以进行代码的复用。
3.private修饰参数
若父类方法中有参数或方法是被private修饰,则使用时不能进行使用。
class animal{ private String name; public int age; public void eat(){ System.out.println("chi()"); } } public static void main(String[] args) { Dog dog = new Dog(); System.out.println(dog.name+"hh"); }
此时调用时则会进行报错。
4.(面试问题)子类继承了父类那些东西?
答:除构造方法之外的所有都被继承了。
5.super关键字
子类的构造需要先帮助父类对象进行构造(调用父类的构造方法)。
class Animal{ private String name; public int age; public void eat(){ System.out.println("chi()"); } public Animal(String name){ this.name=name; } } class Dog extends Animal{ public String sex; public Dog(String name,String sex){ super(name); //注:用super来给父类构造时要放到第一行,否则会报错。 this.sex=sex; } public void crow(String name){ System.out.println("wangwang"); } }
否则程序会进行报错。
super的三种使用方式:
- super():调用父类的构造方法(必须放到第一行)
- super.data:调用父类的成员属性
- super.func:调用父类的成员方法
6.代码的执行顺序
- 父类的static{}
- 子类的static{}
- 父类的实例代码块{}
- 父类的构造函数
- 子类的实例代码块{}
- 子类的构造函数
静态的一定先执行,只执行一次。
7.复杂的继承关系
class A{ } class B extends A{ } class C extends B{ } class D extends C{ }
注:这种继承关系最多不要超过三层,若不想被继承需要使用final来修饰来防止不被继承。
8.继承的注意事项
- 使用extends
- Java中一个子类,只能继承一个父类
- 子类会继承父类的所有public的字段和方法
- 对于父类的private方法和字段,子类是无法访问的(并不是无法继承)
9.继承时,相同名属性的分布
class A{ public int a = 1; } class B extends A{ public int a = 2; public int b = 3; } public class testw { public static void main(String[] args) { B b = new B(); System.out.println(b.a); } }
这种时候的调用a时,会调用子类的a,而不会调用父类的a。
三、访问修饰限定符
public :公共权限
所有的文件都可以进行访问
private,:私有权限
只有在当前类中可以进行访问
protected:受保护权限
在继承时使用,在父类中有protected的属性或方法在不同包中子类继承父类时可以进行调用,使用super关键字进行调用
default:默认包访问权限
只能在当前包中进行访问
四、final:
- final来修饰常量,int a = 10;
- final来修饰类,final class A {},这个类叫做密封类,不想被继承时使用。
- final来修饰方法,这个方法叫做密封方法。
五、组合
像下面这种关系就叫组合
class Student{ //类 } class teacher{ //类 } class school{ public Student[] student; public teacher[] teacher; }
六、多态
字面意思:一种事物多种形态
1.向上转型
子类对象给父类
Animal animal = new Dog("张三");
注意问题:
在Dog子类对象中创建 变量a;
在Animal父类中创建 变量b;
Animal animal = new Dog("张三"); System.out.println(animal.b); System.out.println(animal.a); //报错,父类对象无法调用子类对象 Dog dog = new Dog("李四"); System.out.println(dog.b); System.out.println(dog.a);
此时animal的类型是Animal,所以只能访问Animal类自己的成员。
向上转型的三个时机:
- 直接赋值:
Animal animal = new Dog("张三");
- 传值:
public static void main(String[] args) { func(animal); //这三种发生向上转型 func(dog); func(new Dog("王五")); } public static void func(Animal animal){ }
- 返回值:
public static void main(String[] args) { Animal animal1 = func1(); } public static Animal func1(){ Dog dog = new Dog("张三"); return dog; }
2.向下转型
父类对象给子类
public static void main(String[] args) { Animal animal = new Dog("张三"); Dog dog = (Dog) animal; dog.crow(); }
注意事项:
public static void main(String[] args) { Animal animal = new Animal("张三"); Dog dog = (Dog) animal; dog.crow(); }
此时代码会进行报错,回报一个类型转换错误
所以说向下转型,必须要进行向上转型。
避免错修改:
//判断一下animal 是不是 Dog 的实例。 if(animal instanceof Dog){ Dog dog = (Dog) animal; dog.crow(); }
如果animal引用了Dog则返回true,否则false。
这样就安全了。
3.重写
class Animal{ public void eat(){ System.out.println("chi()"); } } class Dog extends Animal{ @Override //注解:标识在这里发生了重写 public void eat() { System.out.println("he()"); } } public static void main(){ Animal animal = new Dog("花花"); animal.eat(); }
重载(overload)
1.方法名相同
2.参数列表不同(个数和类型)
3.返回值不做要求
重写(override)
1.方法名相同
2.参数列表相同(个数和类型)
3.返回值相同(若返回值构成协变类型)
协变类型:子类的返回值与父类之间返回值是继承关系
class Animal{ public Animal eat(){ System.out.println("chi()"); return new Animal("小花"); } } class Dog extends Animal{ @Override public Dog eat() { System.out.println("he()"); return new Dog("huahua"); } }
此时就构成了协变类型
动态绑定:
1.一定要发生向上转型
2.父类和子类有同名的重写(覆写/覆盖)方法
3.最后通过父类的引用来调用子类和父类的这个同名的覆盖方法。
此时会发生动态绑定,或者叫做运行时绑定。
注意: 在构造函数中也可以发生动态绑定(一个坑)
class Animal{ public void eat(){ System.out.println("chi()"); } public Animal(String name){ eat(); //发生动态绑定 this.name=name; } } class Dog extends Animal{ public Dog(String name){ super(name); } public void eat() { System.out.println("he()"); } } public static void main(String[] args) { Animal animal = new Dog("花花"); }
此时在父类构造方法中发生动态绑定
重写的注意事项
1.如果当前方法是静态方法,是不可以被重写的
2.子类如果要重写父类方法,那么子类的访问修饰权限要大于等于父类的权限
3.父类中要被重写的方法一定不能是,private(私有)。
4.被final修饰的方法不能被重写(密封方法)。
4.理解多态
class Shape{ public void draw(){ } } class Cycle extends Shape{ public void draw(){ //来重写父类方法 System.out.println("矩形"); } } class Rect extends Shape{ public void draw(){ //重写父类方法 System.out.println("圆形"); } } public class testDome { public static void drawMap(Shape shape){ shape.draw(); //调用父类方法,子类方法进行重写发生动态绑定打印子类方法 } public static void main(String[] args) { Cycle cycle = new Cycle(); //new子类对象 Rect rect = new Rect(); //new子类对象 drawMap(cycle); //传参时发生向上转型 drawMap(rect); //传参时发生向上转型 } }
七、抽象类
包含抽象方法的类就是抽象类
抽象方法是什么:被关键字abstract修饰的方法,这个方法可以没有具体的实现。
abstract class Shape{ //密封类 public abstract void draw(); //密封方法 }
抽象类的注意事项
- 抽象类可以被继承,也可以发生动态绑定,向上转型。
- 抽象类不可以被实例化
- 抽象类中的方法一定要被子类重写
- 抽象类存在的意义就是为了被继承,因为不能被实例化
- 如果一个抽象类继承了抽象类,那么可以不重写这个抽象方法。但是这个抽象类再次被一个普通类继承,就需要重写抽象方法。
- 抽象方法不能是private
- 可以包含普通的方法
- 抽象类不能被final修饰。
八、接口
使用关键字interface来修饰的。
1.接口的细节
- 接口当中的方法默认是public abstract 不能有具体实现
- 接口不能实例化
- 接口当中的方法 默认是public static final
- 类和接口直接的关系是implements,此时接口中的所有方法,都要被重写。
- 接口也可以发生向上转型 - 》 运行时绑定(动态绑定)
- JDK1.8开始,接口当中的方法可以有具体的实现,但这个方法一定要被default修饰。
- 在Java中一个类可以实现多个接口。
- 类和接口是implements,接口和接口之间是extends
interface IShape{ //接口 int a = 10; //参数默认为 public static final void draw(); //方法默认为 public abstract default void func1(){ //jdk1.8开始接口中方法有具体的实现,这个方法一定要被default修饰。 System.out.println("123"); } } class Cycle implements IShape{ @Override public void draw(){ System.out.println("○"); } } public class testDome { public static void func(IShape iShape){ iShape.draw(); } public static void main(String[] args) { //IShape iShape = new IShape(); //不能进行实例化 IShape iShape = new Cycle(); //发生向上转型 func(iShape); } }
interface A{ } interface B{ } interface C extends A,B{ }
2.Comparable接口
在使用自定义类型时要使用Comparable接口
class Student implements Comparable<Student>{ public String name; public int age; public Student(String name,int age){ this.name = name; this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Student o) { //对自定义的数据进行排序 //比较的规则 /*if (this.age > o.age){ return 1; //正值 }else if (this.age > o.age){ return -1; }else{ return 0; }*/ //return this.age - o.age; //简化方法 return this.name.compareTo(o.name); //在String中实习了compareTo方法 } } public class testDome { public static void main(String[] args) { Student[] student = new Student[3]; student[0] = new Student("caocao",18); student[1] = new Student("liubei",26); student[2] = new Student("sunquan",22); Arrays.sort(student); //数组排序 System.out.println(Arrays.toString(student)); //数组打印 } }
3.比较器(Comparator)
//类同上面Student不实现接口。 //同包不同类 public class AgeComparator implements Comparator<Student>{ @Override public int compare(Student o1, Student o2) { return o1.age-o2.age; } } //同包不同类 public class NameComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.name.compareTo(o2.name); } } //主程序 public static void main(String[] args) { Student[] student = new Student[3]; student[0] = new Student("caocao",18); student[1] = new Student("liubei",26); student[2] = new Student("sunquan",22); NameComparator nameComparator = new NameComparator(); Arrays.sort(student,nameComparator); System.out.println(Arrays.toString(student)); }
使用比较器更方便,你想使用什么比较就自己实现一个比较器。
相比于Comparable来说,一旦类写死了一种比较方式那么就不能轻易修改了
3.Cloneable接口
Cloneable接口是一个空接口(标识接口),只是代表这个类是可以被克隆的。
class Student1 implements Cloneable{ //这个接口代表着这个类可以被克隆 public String name; public int age; public Student1(String name,int age){ this.name = name; this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } //Override Methods 中的clone @Override protected Object clone() throws CloneNotSupportedException { //接口中没有clone方法,所以需要重写Object的方法 Student1 student1 = (Student1) super.clone(); //调用父类的克隆方法给了Student1 return student1; } } public class testDome1 { public static void main(String[] args) throws CloneNotSupportedException { Student1 student1 = new Student1("caocao",18); Student1 student2 = (Student1)student1.clone(); System.out.println(student1); System.out.println(student2); } }
Cloneable中深浅拷贝问题:
浅拷贝
class Part implements Cloneable{ public int m = 10; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Student1 implements Cloneable{ //这个接口代表着这个类可以被克隆 public String name; public int age; public Part a; public Student1(String name,int age){ this.name = name; this.age = age; this.a = new Part(); } @Override public String toString() { return "Student1{" + "name='" + name + '\'' + ", age=" + age + ", a=" + a + '}'; } //Override Methods 中的clone @Override protected Object clone() throws CloneNotSupportedException { //接口中没有clone方法,所以需要重写Object的方法 Student1 student1 = (Student1) super.clone(); //调用父类的克隆方法给了Student1 student1.a = (Part)this.a.clone(); return student1; } } public class testDome1 { public static void main(String[] args) throws CloneNotSupportedException { Student1 student1 = new Student1("caocao",18); Student1 student2 = (Student1)student1.clone(); System.out.println(student1); System.out.println(student2); } }
以上方法是更改浅拷贝为深拷贝
这篇关于面向对象编程(包+继承)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-09-20接口模块封装入门教程
- 2024-09-20请求动作封装入门教程
- 2024-09-20登录鉴权学习:新手入门教程
- 2024-09-20后台管理开发学习:新手入门指南
- 2024-09-20后台管理系统开发学习:从入门到实践
- 2024-09-20后台开发学习:从入门到初级实战指南
- 2024-09-20后台综合解决方案学习:从入门到实践
- 2024-09-20接口模块封装学习入门指南
- 2024-09-20请求动作封装学习:新手入门教程
- 2024-09-20登录鉴权入门:打造安全的用户认证系统