JAVA零基础入门——面向对象

1.继承

1.1 继承概念

继承的概念:继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
我们将"继承概念"分为两类:
子类 (Subclass) - 子,从另一个类继承的类
超类 (Superclass) - 父,被继承的类

要从类继承,请使用 extends关键字,类的继承格式:
class 父类 {
}
 
class 子类 extends 父类 {
}

为什么要继承类:

  • 当我们开发过程中,对于不同的类中,需要用到同样的属性字段时,我们可以使用继承
  • 继承可以减少代码的重复性,提高代码的可维护性

我们创建一个学生类,再分别创建小学和高中分别继承学生信息为例:

package my.java.study;/*学生信息类*/
public class StudentInfo {private String studentName;//姓名private String studentNo;//学号private int studentAge;//年龄private String studentGender;//性别/*姓名Set*/public void setStudentName(String studentName) {this.studentName = studentName;}/*姓名Get*/public String getStudentName() {return studentName;}/*学号Set*/public void setStudentNo(String studentNo) {this.studentNo = studentNo;}/*学号Get*/public String getStudentNo() {return studentNo;}/*年龄Set*/public void setStudentAge(int studentAge) {this.studentAge = studentAge;}/*年龄Get*/public int getStudentAge() {return studentAge;}/*性别Set*/public void setStudentGender(String studentGender) {this.studentGender = studentGender;}/*性别Get*/public String getStudentGender() {return studentGender;}
}
package my.java.study;
/*小学生*/
public class PrimarySchoolStudent extends  StudentInfo {private int CalligraphyNum;//书法课程数//书法课程数setpublic void setCalligraphyNum(int calligraphyNum) {CalligraphyNum = calligraphyNum;}//书法课程数getpublic int getCalligraphyNum() {return CalligraphyNum;}
}
package my.java.study;
/*高中生*/
public class HighSchoolStudent extends StudentInfo {private int physicsNum;//物理课程数private int chemistryNum;//化学课程数//物理课程数setpublic void setPhysicsNum(int physicsNum) {this.physicsNum = physicsNum;}//物理课程数getpublic int getPhysicsNum() {return physicsNum;}//化学课程数setpublic void setChemistryNum(int chemistryNum) {this.chemistryNum = chemistryNum;}//化学课程数getpublic int getChemistryNum() {return chemistryNum;}
}

import my.java.study.*;public class Main {public static void main(String[] args)  {/*继承*/PrimarySchoolStudent ps = new PrimarySchoolStudent();ps.setStudentName("王子豪");ps.setStudentNo("202409008");ps.setStudentAge(7);ps.setStudentGender("男");ps.setCalligraphyNum(2);System.out.printf("大家好,我是一名小学生,我叫%s,我是%s生,我今年%d岁了,我每周需要上%d节书法课。",ps.getStudentName(),ps.getStudentGender(), ps.getStudentAge(),ps.getCalligraphyNum());HighSchoolStudent hs = new HighSchoolStudent();hs.setStudentName("刘雯");hs.setStudentNo("2024090080098");hs.setStudentAge(17);hs.setStudentGender("女");hs.setPhysicsNum(5);hs.setChemistryNum(4);System.out.printf("大家好,我是一名高中生,我叫%s,我是%s生,我今年%d岁了,我每周需要上%d节物理课和%d节化学课。",hs.getStudentName(),hs.getStudentGender(), hs.getStudentAge(),hs.getPhysicsNum(),hs.getChemistryNum());}
}
1.2 继承的类型和特性

继承类型:需要注意的是 Java 不支持多继承,但支持多重继承

继承特性:

  • 子类拥有父类非 private 的属性、方法。
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  • 子类可以用自己的方式实现父类的方法。
  • Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
  • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。 
1.3 继承关键字

继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承 Object(这个类在 java.lang 包中,所以不需要 import)祖先类。

extends关键字:类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。
implements关键字:使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口
super关键字:我们可以通过 super 关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用,引用当前对象,即它所在的方法或构造函数所属的对象实例。
final关键字:final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写
final声明类:
final class 类名 {//类体}
final声明方法:
修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}

注: final 定义的类,其中的属性、方法不是 final 的。

使用implements 实现接口多继承示例:

public interface A {public void eat();public void sleep();
}public interface B {public void show();
}public class C implements A,B {
}

使用super和this关键字示例(ShowStudentInfo方法):

package my.java.study;/*学生信息类*/
public class StudentInfo {private String studentName;//姓名private String studentNo;//学号private int studentAge;//年龄private String studentGender;//性别/*姓名Set*/public void setStudentName(String studentName) {this.studentName = studentName;}/*姓名Get*/public String getStudentName() {return studentName;}/*学号Set*/public void setStudentNo(String studentNo) {this.studentNo = studentNo;}/*学号Get*/public String getStudentNo() {return studentNo;}/*年龄Set*/public void setStudentAge(int studentAge) {this.studentAge = studentAge;}/*年龄Get*/public int getStudentAge() {return studentAge;}/*性别Set*/public void setStudentGender(String studentGender) {this.studentGender = studentGender;}/*性别Get*/public String getStudentGender() {return studentGender;}//显示学生信息public  void ShowStudentInfo() {System.out.println("Student Name: " + studentName);}
}
package my.java.study;
/*高中生*/
public class HighSchoolStudent extends StudentInfo {private int physicsNum;//物理课程数private int chemistryNum;//化学课程数//物理课程数setpublic void setPhysicsNum(int physicsNum) {this.physicsNum = physicsNum;}//物理课程数getpublic int getPhysicsNum() {return physicsNum;}//化学课程数setpublic void setChemistryNum(int chemistryNum) {this.chemistryNum = chemistryNum;}//化学课程数getpublic int getChemistryNum() {return chemistryNum;}//显示学生信息public  void ShowStudentInfo() {System.out.println("highStudent Name: " + getStudentName());}public void ShowTest(){this.ShowStudentInfo();//调用自己方法super.ShowStudentInfo();//调用父类方法}
}

import my.java.study.*;public class Main {public static void main(String[] args)  {/*继承*/HighSchoolStudent hs = new HighSchoolStudent();hs.setStudentName("刘雯");hs.setStudentNo("2024090080098");hs.setStudentAge(17);hs.setStudentGender("女");hs.setPhysicsNum(5);hs.setChemistryNum(4);System.out.printf("大家好,我是一名高中生,我叫%s,我是%s生,我今年%d岁了,我每周需要上%d节物理课和%d节化学课。",hs.getStudentName(),hs.getStudentGender(), hs.getStudentAge(),hs.getPhysicsNum(),hs.getChemistryNum());hs.ShowTest();}
}
 1.4 构造器

子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。
如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

实例代码:

package my.java.study;/*学生信息类*/
public class StudentInfo {private String studentName;//姓名private String studentNo;//学号private int studentAge;//年龄private String studentGender;//性别//无参构造器public StudentInfo(){System.out.println("学生你好!");}//带参构造器public StudentInfo(String studentName) {this.studentName=studentName;}/*姓名Set*/public void setStudentName(String studentName) {this.studentName = studentName;}/*姓名Get*/public String getStudentName() {return studentName;}/*学号Set*/public void setStudentNo(String studentNo) {this.studentNo = studentNo;}/*学号Get*/public String getStudentNo() {return studentNo;}/*年龄Set*/public void setStudentAge(int studentAge) {this.studentAge = studentAge;}/*年龄Get*/public int getStudentAge() {return studentAge;}/*性别Set*/public void setStudentGender(String studentGender) {this.studentGender = studentGender;}/*性别Get*/public String getStudentGender() {return studentGender;}
}
package my.java.study;
/*小学生*/
public class PrimarySchoolStudent extends  StudentInfo {private int CalligraphyNum;//书法课程数//无参构造器 自动继承 StudentInfo的无参构造函数public PrimarySchoolStudent() {}//书法课程数setpublic void setCalligraphyNum(int calligraphyNum) {CalligraphyNum = calligraphyNum;}//书法课程数getpublic int getCalligraphyNum() {return CalligraphyNum;}
}
package my.java.study;
/*高中生*/
public class HighSchoolStudent extends StudentInfo {private int physicsNum;//物理课程数private int chemistryNum;//化学课程数//带参构造器public HighSchoolStudent(String studentName){super(studentName);//调用父类带参构造器}//物理课程数setpublic void setPhysicsNum(int physicsNum) {this.physicsNum = physicsNum;}//物理课程数getpublic int getPhysicsNum() {return physicsNum;}//化学课程数setpublic void setChemistryNum(int chemistryNum) {this.chemistryNum = chemistryNum;}//化学课程数getpublic int getChemistryNum() {return chemistryNum;}
}

import my.java.study.*;public class Main {public static void main(String[] args)  {/*继承*/PrimarySchoolStudent ps = new PrimarySchoolStudent();ps.setStudentName("王子豪");ps.setStudentNo("202409008");ps.setStudentAge(7);ps.setStudentGender("男");ps.setCalligraphyNum(2);System.out.printf("大家好,我是一名小学生,我叫%s,我是%s生,我今年%d岁了,我每周需要上%d节书法课。\r\n",ps.getStudentName(),ps.getStudentGender(), ps.getStudentAge(),ps.getCalligraphyNum());HighSchoolStudent hs = new HighSchoolStudent("刘雯");//hs.setStudentName("刘雯");hs.setStudentNo("2024090080098");hs.setStudentAge(17);hs.setStudentGender("女");hs.setPhysicsNum(5);hs.setChemistryNum(4);System.out.printf("大家好,我是一名高中生,我叫%s,我是%s生,我今年%d岁了,我每周需要上%d节物理课和%d节化学课。",hs.getStudentName(),hs.getStudentGender(), hs.getStudentAge(),hs.getPhysicsNum(),hs.getChemistryNum());}
}

 运行结果:

2.重写/重载

2.1 重写

重写(Override)是指子类定义了一个与其父类中具有相同名称、参数列表和返回类型的方法,并且子类方法的实现覆盖了父类方法的实现。 即外壳不变,核心重写!

重写的好处在于子类可以根据需要,定义特定于自己的行为。也就是说子类能够根据需要实现父类的方法。这样,在使用子类对象调用该方法时,将执行子类中的方法而不是父类中的方法。

重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。

当需要在子类中调用父类的被重写方法时,要使用 super 关键字。

重写规则

  • 参数列表与被重写方法的参数列表必须完全相同。
  • 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)。
  • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。
  • 父类的成员方法只能被它的子类重写。
  • 声明为 final 的方法不能被重写。
  • 声明为 static 的方法不能被重写,但是能够被再次声明。
  • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
  • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
  • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
  • 构造方法不能被重写。
  • 如果不能继承一个类,则不能重写该类的方法。

 重写实例(获取学生信息方法):

package my.java.study;/*学生信息类*/
public class StudentInfo {private String studentName;//姓名private String studentNo;//学号private int studentAge;//年龄private String studentGender;//性别/*姓名Set*/public void setStudentName(String studentName) {this.studentName = studentName;}/*姓名Get*/public String getStudentName() {return studentName;}/*学号Set*/public void setStudentNo(String studentNo) {this.studentNo = studentNo;}/*学号Get*/public String getStudentNo() {return studentNo;}/*年龄Set*/public void setStudentAge(int studentAge) {this.studentAge = studentAge;}/*年龄Get*/public int getStudentAge() {return studentAge;}/*性别Set*/public void setStudentGender(String studentGender) {this.studentGender = studentGender;}/*性别Get*/public String getStudentGender() {return studentGender;}//获取学生信息public String GetStudentInfo() {return studentName + ", " + studentNo + ", " + studentAge + ", " + studentGender;}
}
package my.java.study;
/*小学生*/
public class PrimarySchoolStudent extends  StudentInfo {private int CalligraphyNum;//书法课程数//书法课程数setpublic void setCalligraphyNum(int calligraphyNum) {CalligraphyNum = calligraphyNum;}//书法课程数getpublic int getCalligraphyNum() {return CalligraphyNum;}//重写——获取学生信息public String GetStudentInfo() {String str= super.GetStudentInfo();//super 关键字调用父类方法String str1="我是一名小学生";str1+="我一周需要上"+CalligraphyNum+"节书法课";return str+str1;}
}

import my.java.study.*;public class Main {public static void main(String[] args)  {/*继承*/PrimarySchoolStudent ps = new PrimarySchoolStudent();ps.setStudentName("王子豪");ps.setStudentNo("202409008");ps.setStudentAge(7);ps.setStudentGender("男");ps.setCalligraphyNum(2);System.out.printf("大家好,我是一名小学生,我叫%s,我是%s生,我今年%d岁了,我每周需要上%d节书法课。\r\n",ps.getStudentName(),ps.getStudentGender(), ps.getStudentAge(),ps.getCalligraphyNum());System.out.println(ps.GetStudentInfo());}
}
2.2 重载

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
重载规则:

  • 被重载的方法必须改变参数列表(参数个数或类型不一样);
  • 被重载的方法可以改变返回类型;
  • 被重载的方法可以改变访问修饰符;
  • 被重载的方法可以声明新的或更广的检查异常;
  • 方法能够在同一个类中或者在一个子类中被重载。
  • 无法以返回值类型作为重载函数的区分标准。

 重载实例(计算数字之和方法):


public class Main {public static void main(String[] args)  {System.out.println("整数之和:"+CalSum(new int[]{1,2,3,4,5}));System.out.println("小数之和:"+CalSum(new float[]{1.3f,2.54f,3.6f,4.09f,5.5f}));}//计算数字之和public static int CalSum(int...numbers){int sum = 0;for(int i : numbers){sum += i;}return sum;}//计算小数之和public static float CalSum(float...numbers){float sum = 0;for (float number : numbers) {sum += number;}return sum;}
}
2.3 重写与重载的区别
区别点重载方法重写方法
参数列表必须修改一定不能修改
返回类型可以修改一定不能修改
异常可以修改可以减少或删除,一定不能抛出新的或者更广的异常
访问可以修改一定不能做更严格的限制(可以降低限制)

 总结

方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

  • 方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
  • 方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
  • 方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

3.多态

什么是多态

  • 多态意味着"多种形式",当我们有许多通过继承相互关联的类时,就会产生多态性,比如我们前面讲到的继承、重写、重载等,还有接口、抽象类和抽象方法等
  • 多态是同一个行为具有多个不同表现形式或形态的能力
  • 多态就是同一个接口,使用不同的实例而执行不同操作,比如打印机的彩色打印和黑白打印
  • 多态性是对象多种表现形式的体现,比如键盘的同一个按键在不同系统中的功能不同

多态的优点

  • 消除类型之间的耦合关系
  • 可替换性
  • 可扩充性
  • 接口性
  • 灵活性
  • 简化性

多态存在的必要条件

  • 继承
  • 重写
  • 父类引用指向子类对象:Parent p = new Child();

4.内部类

内部类也称为嵌套类,就是类中的类,嵌套类的目的是将属于同一类的类分组,这使代码更具可读性和可维护性。

内部类可以是private 私有的或 protected受保护的或者public

内部类可以是静态的

内部类可以访问外部类的属性和方法

 内部类实例:

package my.java.study;/*学生信息类*/
public class StudentInfo {private String studentName;//姓名private String studentNo;//学号private int studentAge;//年龄private String studentGender;//性别/*姓名Set*/public void setStudentName(String studentName) {this.studentName = studentName;}/*姓名Get*/public String getStudentName() {return studentName;}/*学号Set*/public void setStudentNo(String studentNo) {this.studentNo = studentNo;}/*学号Get*/public String getStudentNo() {return studentNo;}/*年龄Set*/public void setStudentAge(int studentAge) {this.studentAge = studentAge;}/*年龄Get*/public int getStudentAge() {return studentAge;}/*性别Set*/public void setStudentGender(String studentGender) {this.studentGender = studentGender;}/*性别Get*/public String getStudentGender() {return studentGender;}//内部类 JuniorStudentpublic  class  JuniorStudent{private String address;//地址public void setAddress(String address) {this.address = address;}public String getAddress() {return address;}}
}

调用内部类:

import my.java.study.*;public class Main {public static void main(String[] args)  {StudentInfo si = new StudentInfo();StudentInfo.JuniorStudent js=si.new JuniorStudent();}
}

5.抽象类

数据抽象是隐藏某些细节并仅向用户显示基本信息的过程。
抽象类:是一个不能用于创建对象的受限类(要访问它,必须从另一个类继承)。

抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。

抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。

创建抽象类,使用关键字abstract

抽象类可以有抽象方法和常规方法
抽象方法: 只能在抽象类中使用,并且它没有主体。主体由子类(继承自)提供。

定义抽象方法使用关键字abstract。

声明抽象方法会造成以下两个结果:

  • 如果一个类包含抽象方法,那么该类必须是抽象类。
  • 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。

继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象

抽象类及抽象方法实例:

package my.java.study;
//抽象类Employee
public abstract class Employee {private String emplyeeName;//员工姓名private String emplyeeTel;//员工电话private String emplyeeAddress;//员工住址//员工姓名Setpublic void SetEmplyeeName(String emplyeeName) {this.emplyeeName = emplyeeName;}//员工姓名Getpublic String getEmplyeeName() {return emplyeeName;}//员工电话Setpublic void SetEmplyeeTel(String emplyeeTel) {this.emplyeeTel = emplyeeTel;}//员工电话Getpublic String getEmplyeeTel() {return emplyeeTel;}//员工住址Setpublic void SetEmplyeeAddress(String emplyeeAddress) {this.emplyeeAddress = emplyeeAddress;}//员工住址Getpublic String getEmplyeeAddress() {return emplyeeAddress;}//常规方法——获取员工信息public String GetEmplyeeInfo(){return emplyeeName + " " + emplyeeTel + " " + emplyeeAddress;}//抽象方法——获取员工住址public abstract String GetEmplyeeAddress();
}
package my.java.study;
//普通员工——继承抽象类Employee
public class CommonStaff extends Employee {private String workPosition;//工位//工位Setpublic void setWorkPosition(String workPosition) {this.workPosition = workPosition;}//工位Getpublic String getWorkPosition() {return workPosition;}//抽象方法具体化@Overridepublic String GetEmplyeeAddress() {return getEmplyeeAddress();}
}

import my.java.study.*;public class Main {public static void main(String[] args)  {/*抽象类*/CommonStaff cs = new CommonStaff();cs.setWorkPosition("001");cs.SetEmplyeeName("徐文超");cs.SetEmplyeeTel("13775175810");cs.SetEmplyeeAddress("常州市新北区藻江花园");System.out.println(cs.GetEmplyeeInfo());System.out.println(cs.GetEmplyeeAddress());}}

6.封装

什么是封装

在面向对象程式设计方法中,封装(Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
要访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。
封装的优点

  • 良好的封装能够减少耦合。
  • 类内部的结构可以自由修改。
  • 可以对成员变量进行更精确的控制。
  • 隐藏信息,实现细节。

封装的实现

  1. 修改属性的可见性来限制对属性的访问(一般限制为private)
  2. 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问

一般我们创建实体类的时候,通过set和get公共方法来获取字段值的方式,就是封装

7.接口

什么是接口

接口(Interface)是一个完全抽象类,定义接口使用interface关键字

接口特性
接口无法被实例化,但是可以被实现,一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。
接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
接口中的方法都是公有的。

接口的继承
一个类通过继承接口的方式,从而来继承接口的抽象方法,类继承接口使用implements关键字
接口可以继承单个接口,也可以继承多个接口,接口继承接口使用extends关键字

注:
JDK 1.8 以后,接口里可以有静态方法和方法体了。
JDK 1.8 以后,接口允许包含具体实现的方法,该方法称为"默认方法",默认方法使用 default 关键字修饰。
JDK 1.9 以后,允许将方法定义为 private,使得某些复用的代码不会把方法暴露出去。

7.1 接口的实现和继承

定义接口的语法

 [可见度] interface 接口名称  {
        // 声明变量
        // 抽象方法
}

接口继承接口语法

  [可见度] interface 接口名称 [extends 其他的接口名] {
        // 声明变量
        // 抽象方法
}

继承多个接口,使用逗号分割符:

[可见度] interface 接口名称 [extends 其他的接口名1,其他的接口名2]

类继承接口语法

当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。

   [可见度] class 类名称 [implements 其他的接口名] {
        // 声明变量
        // 重写接口方法
}

继承多个接口,使用逗号分割符:

 [可见度] class 类名称 [implements 其他的接口名1,其他的接口名2]

重写接口中声明的方法时,需要注意以下规则:

  • 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
  • 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
  • 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。

实例代码:

package my.java.study;
//计算求和接口
public interface CalSum {public int calIntSum(int...numbers);public float calFloatSum(float...numbers);//静态类方法——double求和public  static double calDoubleSum(double...numbers) {double sum = 0;for (double number : numbers) {sum += number;}return sum;}
}
package my.java.study;
//计算类——继承计算求和接口
public class CalHelper  implements CalSum{//计算整数求和@Overridepublic int calIntSum(int... numbers) {int sum = 0;for (int number : numbers) {sum += number;}return sum;}//计算小数求和@Overridepublic float calFloatSum(float... numbers) {float sum = 0;for (float number : numbers) {sum += number;}return sum;}
}

import my.java.study.*;public class Main {public static void main(String[] args)  {/*接口*///类方法求和CalHelper calHelper = new CalHelper();int sum1=calHelper.calIntSum(new int[]{1,2,3,4,5});System.out.println("整数求和:"+sum1);float sum2=calHelper.calFloatSum(new float[]{1.23f,2.4f,3.6f,4.6f,5.5f});System.out.println("float求和:"+sum2);//接口计算求和double sum3=CalSum.calDoubleSum(new double[]{1.45,2.35,4.6,5.55});System.out.println("double求和:"+sum3);}
}

8.枚举

枚举定义

  • 枚举是一个特殊的"类",它表示一组常量
  • 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割。
  • 枚举定义,应为大写字母

枚举方法
enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Serializable 和 java.lang.Comparable 两个接口。
values(), ordinal() 和 valueOf() 方法位于 java.lang.Enum 类中:

  • values() 返回枚举类中所有的值。
  • ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
  • valueOf()方法返回指定字符串值的枚举常量。

枚举实例 


public class Main {public static void main(String[] args)  {/*枚举*///内部使用枚举System.out.println(Color.RED);//迭代遍历枚举元素for(Color c : Color.values()){System.out.println("枚举值:"+c);//索引值默认 从0开始,第一个枚举默认0,后面顺延System.out.println("枚举索引:"+c.ordinal());}//返回指定字符串值的枚举常量Color cRed=Color.valueOf("RED");System.out.println("valueOf方法:"+cRed);cRed.colorInfo();//switch语句中使用枚举Color c1 = Color.BLUE;switch (c1){case BLUE:System.out.println("Blue");break;case RED:System.out.println("Red");break;case ORANGE:System.out.println("Orange");break;case YELLOW:System.out.println("Yellow");break;default:System.out.println("GREEN");break;}}//定义颜色枚举enum Color{RED,ORANGE,YELLOW,GREEN,BLUE;// 构造函数private Color(){System.out.println("Constructor called for : " + this.toString());}//方法public void colorInfo(){System.out.println("Universal Color");}}
}

9.包

包(package)的作用

  1. 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
  2. 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
  3. 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等。
开发者可以自己把一组类和接口等打包,并定义自己的包。而且在实际开发中这样做是值得提倡的,当你自己完成类的实现之后,将相关的类分组,可以让其他的编程者更容易地确定哪些类、接口、枚举和注释等是相关的。
由于包创建了新的命名空间(namespace),所以不会跟其他包中的任何名字产生命名冲突。使用包这种机制,更容易实现访问控制,并且让定位相关类更加简单。

package 的目录结构
类放在包中会有两种主要的结果:

  • 包名成为类名的一部分。
  • 包名必须与相应的字节码所在的目录结构相吻合。

包语句的语法格式:

package pkg1[.pkg2[.pkg3…]]; 

包引入的语法格式:

import package1[.package2…].(classname|*); 

 包引入实例

import java.util.ArrayList; // 引入 java.util 包中的 ArrayList 类
import java.util.*; // 引入 java.util 包中的所有类import com.example.MyClass; // 引入 com.example 包中的 MyClass 类
import com.example.*; // 引入 com.example 包中的所有类

10.反射

反射(Reflection)是一个强大的特性,它允许程序在运行时查询、访问和修改类、接口、字段和方法的信息。反射提供了一种动态地操作类的能力,这在很多框架和库中被广泛使用,例如Spring框架的依赖注入。

反射 API
反射 API 提供了一系列的类和接口来操作 Class 对象。主要的类包括:

  • java.lang.Class:表示类的对象。提供了方法来获取类的字段、方法、构造函数等。
  • java.lang.reflect.Field:表示类的字段(属性)。提供了访问和修改字段的能力。
  • java.lang.reflect.Method:表示类的方法。提供了调用方法的能力。
  • java.lang.reflect.Constructor:表示类的构造函数。提供了创建对象的能力。

工作流程

  1. 获取 Class 对象:首先获取目标类的 Class 对象。
  2. 获取成员信息:通过 Class 对象,可以获取类的字段、方法、构造函数等信息。
  3. 操作成员:通过反射 API 可以读取和修改字段的值、调用方法以及创建对象。
10.1 反射机制核心包

java.lang.reflect 是 反射机制的核心包,提供了操作类及其成员(字段、方法、构造函数等)的类和接口。通过这些 API,开发者可以在运行时动态地查询和修改类的结构。

 java.lang.reflect的主要类和接口详细介绍

 Class类:表示类的对象,提供了获取类信息的方法,如字段、方法、构造函数等。

主要方法说明
getFields()获取所有公共字段
getDeclaredFields()获取所有声明的字段,包括私有字段
getMethods()获取所有公共方法
getDeclaredMethods()获取所有声明的方法,包括私有方法
getConstructors()获取所有公共构造函数
getDeclaredConstructors()获取所有声明的构造函数,包括私有构造函数
getSuperclass()获取类的父类
getInterfaces()获取类实现的所有接口

Field类:表示类的字段(属性),提供了访问和修改字段值的方法。

主要方法说明
get(Object obj)获取指定对象的字段值
set(Object obj, Object value)设置指定对象的字段值
getType()获取字段的数据类型
getModifiers()获取字段的修饰符(如 public、private)

Method类:表示类的方法,提供了调用方法的能力

主要方法说明
invoke(Object obj, Object... args)调用指定对象的方法
getReturnType()获取方法的返回类型
getParameterTypes()获取方法的参数类型
getModifiers()获取方法的修饰符(如 public、private)

Constructor类:表示类的构造函数,提供了创建对象的能力。

主要方法说明
newInstance(Object... initargs)创建一个新实例,使用指定的构造函数参数
getParameterTypes()获取构造函数的参数类型
getModifiers()获取构造函数的修饰符(如 public、private)

反射实例

创建Person类

package my.java.study;public class Person {private String name;private int age;//构造函数public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public void greet(String message) {System.out.println(name + " says: " + message);}
}

反射Person类


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import my.java.study.*;public class Main {public static void main(String[] args)  {/*反射*/try{//获取class对象//Class<?> clazz=Class.forName("my.java.study.Person");//通过名称获取Class<?> clazz=Person.class;//通过对象获取// 创建对象Constructor<?> constructor = clazz.getConstructor(String.class, int.class);Object person = constructor.newInstance("John", 30);// 获取声明的字段 nameField nameField = clazz.getDeclaredField("name");//设置字段为可访问(如果字段是私有的)nameField.setAccessible(true);System.out.println("Name: " + nameField.get(person));// 修改name字段值nameField.set(person, "Doe");System.out.println("Updated Name: " + nameField.get(person));// 调用greet方法Method greetMethod = clazz.getMethod("greet", String.class);greetMethod.invoke(person, "World");}catch(Exception e){System.out.println(e.getMessage());}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/144675.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Kotlin cancel CoroutineScope.launch的任务后仍运行

Kotlin cancel CoroutineScope.launch的任务后仍运行 import kotlinx.coroutines.*fun main() {runBlocking {val coroutineScope CoroutineScope(Dispatchers.IO)val job coroutineScope.launch {var i 0while (i < Int.MAX_VALUE) {iprintln(i)}}// 2ms 取消协程delay(…

输电线路缺陷检测数据集(绝缘子自爆,破损,闪络,鸟巢,防震锤脱落五种缺陷)

输电线路数据集&#xff08;绝缘子自爆&#xff0c;破损&#xff0c;闪络&#xff0c;鸟巢&#xff0c;防震锤脱落五种缺陷&#xff09;包括&#xff1a; 1.绝缘子自爆 2.绝缘子破损绝、闪络 3.鸟巢 4.防震锤脱落 数据增强后的数量 对应数量&#xff1a;1828&#xff0c;1467&a…

新手学习Python第八天——学习笔记

今天08&#xff1a;10才到实验室&#xff0c;昨天晚上感冒了又没睡好所以就来晚了。 师弟送了我一袋感冒灵&#xff0c;希望尽快好。 开始复习昨天的内容 08&#xff1a;29 刚刚弄完建模大赛的报名和校内举办的游园会 一看10&#xff1a;00 1. 递归函数&#xff1a; 1.…

【GESP】C++一级练习BCQM3008,审题更重要,printf的格式化输出

跟BCQM3005一样&#xff0c;都是printf的格式化输出练习题。不过从题目描述过程来看&#xff0c;审题过程比题目本身更重要。 BCQM3008 题目要求 描述 雪花 一片两片三四片&#xff0c; 五片六片七八片&#xff0c; 九片十片无数片&#xff0c; 飞入梅花看不见。 试编一程序…

【C++】C++11-包装器

目录 1、function包装器 2、function包装器包装成员函数指针 2.1 静态成员函数 2.2 非静态成员函数 3、bind包装器 3.1 调整参数顺序 3.2 调整参数个数 1、function包装器 包装器是用来包装可调用对象的&#xff0c;这里的可调用对象主要有函数指针、仿函数、lambda表达…

基于Delphi的题库生成系统

基于Delphi的题库生成系统是一个复杂的项目&#xff0c;涉及到多个模块的设计和实现。以下是一个简化的代码案例&#xff0c;展示了如何使用Delphi构建一个基本的题库生成系统。 1. 数据库设计 首先&#xff0c;你需要设计一个数据库来存储试题信息。一个简单的数据库设计可…

缓存穿透 问题(缓存空对象)

文章目录 1、缓存穿透2、缓存空对象3、AlbumInfoApiController --》getAlbumInfo()4、AlbumInfoServiceImpl --》getAlbumInfo()5、RedisConstant6、请求缓存不存在的数据 1、缓存穿透 2、缓存空对象 3、AlbumInfoApiController --》getAlbumInfo() GetMapping("getAlbumI…

经济基础决定上层建筑,好芯片构建好音质——模拟芯片龙头德州仪器的D类音频放大器TAS6424-Q1

在文娱生活愈加丰富的现时今日,在行驶途中,打开车载音响听听喜爱的音乐,或是直接打开收音机收听不同频段的电台节目,都是行车途中不可或缺的部分。如此看来,汽车是否搭载优秀的音响系统,成为了消费者选购车辆时的重要指标。 而如何让汽车拥有出色的音响主机呢?那就得请出…

Web后端服务平台解析漏洞与修复、文件包含漏洞详解

免责申明 本文仅是用于学习检测自己搭建的Web后端服务平台解析漏洞、文件包含漏洞的相关原理,请勿用在非法途径上,若将其用于非法目的,所造成的一切后果由您自行承担,产生的一切风险和后果与笔者无关;本文开始前请认真详细学习《‌中华人民共和国网络安全法》‌及其所在国…

将有序数组——>二叉搜索树

给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵平衡二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0,-10,5,null,-3,null,9] 也将被视为正确答案…

PyRFC 适用于 Python 的异步、非阻塞 SAP NetWeaver RFC SDK 绑定

Asynchronous, non-blocking SAP NetWeaver RFC SDK bindings for Python. 适用于 Python 的异步、非阻塞 SAP NetWeaver RFC SDK 绑定 Call for Maintainers This project is currently looking for new maintainers. Please see this issue for details. Features Client …

A review on rumour prediction and veracity assessment in online social network

ABSTRACT 在当今时代&#xff0c;社交网络被用作分享个人思想和观点的重要媒介。其背后的主要原因是&#xff0c;它可以轻松地在公众中快速传播信息&#xff0c;并且访问成本非常低。这导致在线社交媒体成为鼓励虚假内容并影响公众舆论及其决策的垫脚石之一。谣言是社交媒体上误…

论文速递!时序预测!DCSDNet:双卷积季节性分解网络,应用于天然气消费预测过程

本期推文将介绍一种新的时序预测方法:双卷积季节性分解网络&#xff08;Dual Convolution withSeasonal Decomposition Network, DCSDNet&#xff09;在天然气消费预测的应用&#xff0c;这项研究发表于《Applied Energy》期刊。 针对天然气消费的多重季节性和非规律性&#x…

木牛科技PMO总监关沨受邀为第四届中国项目经理大会演讲嘉宾

全国项目经理专业人士年度盛会 北京木牛领航科技有限公司PMO总监关沨女士受邀为PMO评论主办的全国项目经理专业人士年度盛会——2024第四届中国项目经理大会演讲嘉宾&#xff0c;演讲议题为“如何培养能打胜仗的项目经理”。大会将于10月26-27日在北京举办&#xff0c;主题为&a…

Android插件化(三)基础之Android应用程序资源的编译和打包过程分析

Android插件化(三)基础之Android应用程序资源的编译和打包过程分析 Android资源加载常规思路 getResourcesForApplication //首先&#xff0c;通过包名获取该包名的Resources对象 Resources res pm.getResourcesForApplication(packageName); //根据约定好的名字&#xff0c…

C++日期类,详细!!!

日期类的练习可以巩固提高之前所学习的知识&#xff0c;还可以完成关于的日期练习 下面是关于日期的对应oj题 KY111 日期差值 计算一年的第几天 累加天数 1.Date.h 头文件部分 看看我们要实现那些接口 1.获取对应月份的天数:GetMonthDay 2. < > …

leetcode41. 缺失的第一个正数,原地哈希表

leetcode41. 缺失的第一个正数 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 解释&#xf…

计算机三级网络技术总结(五)

HTTP端口号为80 三平台一出口&#xff1a;网络平台、业务平台、管理平台和城市宽带出口IEEE802.16最高传输速率为134Mbps链路状态数据库中保存的是全网的拓扑结构图&#xff0c;而非全网完整的路由表在无线局域网中&#xff0c;客户端设备用来访问接入点&#xff08;AP&#xf…

GUI编程17:下拉框、列表框

视频链接&#xff1a;19、下拉框、列表框_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1DJ411B75F?p19&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 1.下拉框 代码示例 package com.yundait.lesson06;import javax.swing.*; import java.awt.*;public class Te…

计算机毕业设计 教师科研信息管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…