ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

面向对象编程(包+继承)

2021-09-10 19:33:09  阅读:124  来源: 互联网

标签:name 继承 void class 面向对象编程 父类 public String


文章目录


一、包

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的三种使用方式:

  1. super():调用父类的构造方法(必须放到第一行)
  2. super.data:调用父类的成员属性
  3. super.func:调用父类的成员方法

6.代码的执行顺序

  1. 父类的static{}
  2. 子类的static{}
  3. 父类的实例代码块{}
  4. 父类的构造函数
  5. 子类的实例代码块{}
  6. 子类的构造函数
    静态的一定先执行,只执行一次。

7.复杂的继承关系

class A{ 
}
class B extends A{
}
class C extends B{
}
class D extends C{
}

注:这种继承关系最多不要超过三层,若不想被继承需要使用final来修饰来防止不被继承。

8.继承的注意事项

  1. 使用extends
  2. Java中一个子类,只能继承一个父类
  3. 子类会继承父类的所有public的字段和方法
  4. 对于父类的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:

  1. final来修饰常量,int a = 10;
  2. final来修饰类,final class A {},这个类叫做密封类,不想被继承时使用。
  3. 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类自己的成员。

向上转型的三个时机:

  1. 直接赋值:
Animal animal = new Dog("张三");
  1. 传值:
public static void main(String[] args) {     
	func(animal);  //这三种发生向上转型
	func(dog);
	func(new Dog("王五"));
}
public static void func(Animal animal){

}
  1. 返回值:
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();  //密封方法
}

抽象类的注意事项

  1. 抽象类可以被继承,也可以发生动态绑定,向上转型。
  2. 抽象类不可以被实例化
  3. 抽象类中的方法一定要被子类重写
  4. 抽象类存在的意义就是为了被继承,因为不能被实例化
  5. 如果一个抽象类继承了抽象类,那么可以不重写这个抽象方法。但是这个抽象类再次被一个普通类继承,就需要重写抽象方法。
  6. 抽象方法不能是private
  7. 可以包含普通的方法
  8. 抽象类不能被final修饰。

八、接口

使用关键字interface来修饰的。

1.接口的细节

  1. 接口当中的方法默认是public abstract 不能有具体实现
  2. 接口不能实例化
  3. 接口当中的方法 默认是public static final
  4. 类和接口直接的关系是implements,此时接口中的所有方法,都要被重写。
  5. 接口也可以发生向上转型 - 》 运行时绑定(动态绑定)
  6. JDK1.8开始,接口当中的方法可以有具体的实现,但这个方法一定要被default修饰。
  7. 在Java中一个类可以实现多个接口。
  8. 类和接口是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);
    }
}

以上方法是更改浅拷贝为深拷贝

标签:name,继承,void,class,面向对象编程,父类,public,String
来源: https://blog.csdn.net/m0_50976823/article/details/119978529

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有