面向对象
面向对象编程思想:将程序模块化的思想。
-
什么是面向对象?
面向对线编程思想诞生之前,程序开发采用的是面向过程的结构化编程方式,是一种面向功能划分的软件结构。
最小粒度细化到方法这一层。
面向过程注重的是每一个步骤,面向对象关注点在于整件事情的模块化结构。
-
类和对象
类和对象的关系
每个对象都有特定的特征:1、属性。2、方法。
属性指的是对象的静态特征,方法是用来描述对象的动态特征。
对象是用来描述客观存在的一个实体,该实体是由一组属性和方法构成。
类(一个Java文件就是一个类)是与对象紧密结合的另外一个概率,类是产生对象的模板,所有的对象都是通过类来创建的。
二者的关系:类是对象的抽象化描述,这些对象具有相同的特征和动作(属性和方法)。对象是类的具体实例。
Java 程序是以类为组织单元,程序运行时的主体是通过类创建的具体对象。
定义类
public class 类名(){
//定义属性,属性名符合驼峰式命名法
public 数据类型 属性名;
//定方法,方法名符合驼峰式命名法
public 返回值类型 方法名(参数列表:数据类型 参数名){
//方法体
}
}
Java 关于返回值的定义分为两类:有返回值和无返回值,有返回值的方法需要在方法定义时指定返回值的数据类型,并在方法体中return 将结果返回给外部调用者,加法运算。
public class test1 {
public static void main (String[] args) {
int num = add(10,10);
System.out.println(num);
}
//有返回值
public static int add(int a,int b){
return a+b;
}
}
如果一个方法不需要进行返回操作,将返回值类型定义为void。
参数列表是指外部在调用该方法时需要传入到方法内部进行运算的数据。
构造函数、构造方法、构造器
构造函数是一种特殊的方法,普通方法是用来描述某个动作的,构造方法是用来创建对象的。
-
方法名必须与类名一致
-
不需要定义返回值类型
public class test1 {
//构造方法,没有返回值类型,名字与类名一致
public test1(){
}
//主方法
public static void main (String[] args) {
int num = add(10,10);
System.out.println(num);
}
//普通方法
public static int add(int a,int b){
return a+b;
}
}
构造函数可分为有参构造和无参构造,有参构造是指带参数的构造函数,无参构造是指没有参数的构造函数。
任何一个类都默认自带一个无参构造函数,如果手动在类中定义一个有参构造,则会覆盖默认的无参构造。
this 关键字
this 用来指代当前类的实例化对象,通过 this 可以调用当前类的属性和方法,比如在有参构造中,通过 this 将外部传入的值赋给当前类的实例化对象。
public Student(int id,String name){
this.id = id;
this.name = name;
//加 this 过后的id和name是当前类的id和name将形参赋值给这个类的id和name
}
this 除了可以在类中访问属性也可以在类中调用方法,类中的方法可以分为两类:构造方法、普通方法。
用 this 调用这两类方法的语法也不同,调用构造函数的语法是 this(参数列表),不能在普通方法中使用 this 来调用构造函数。
用 this 调用普通方法,this.方法名(参数列表),可以在构造函数中使用,也可以在普通方法中使用。
成员变量和局部变量
变量的作用域是指在程序中可以通过变量名来访问该变量的范围,变量的作用域由变量被声明时所在位置决定的。Java 中根据不同的作用域可以将变量分为成员变量和局部变量。
局部变量:如果一个变量在方法中声明,则该变量是局部变量。
成员变量:如果一个变量在方法外类中声明,则该变量是成员变量。
public class HelloWorld{
int num2 = 2; //成员变量
public int test(){
int num1 = 1; //局部变量
}
}
-
成员变量和局部变量的区别在于作用域不同,成员变量的作用域在整个内中,类中的每个方法都可以访问该变量,局部变量的作用域只在定义该变量的方法中,出了方法体就无法访问。
-
成员变量和局部变量的初始值也不同,局部变量不会赋初始值,成员变量会赋初始值,值是由具体得数据类型决定的。
封装
封装是指将类的属性隐藏在内部,外部不能直接访问和修改,通过修改成员变量的可见性,从公有改为私有。
package com.bsj;
import jdk.swing.interop.SwingInterOpUtils;
public class Student {
private int id;
private String name;
private int age;
public void show(){
System.out.println("学生信息如下:");
System.out.println("学生编号:"+id);
System.out.println("学生姓名:"+name);
System.out.println("学生年龄:"+age);
}
public void setId(int id){
this.id = id;
}
public int getId(){
return id;
}
public void setAge(int age){
if (age<=0){
System.out.println("输入的数值有错误!");
age = 18;
}
this.age = age;
}
public int getAget(){
return age;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
封装的核心思想就是尽可能把属性都隐藏在内部,对外提供方法来访问,我们可以在这些方法中添加逻辑处理来实现过滤,以屏蔽错误数据的赋值。
-
修改属性(成员变量)的访问权限为私有,使得外部不能直接访问
-
提供外部可以直接调用的方法
-
在该方法中加入对于属性的逻辑控制,避免出现逻辑上的错误
什么是访问权限?
访问权限是指该属性可以被直接访问的范围,是在属性定义时设定的。
private、默认(不写)、protected、区别在于作用域范围不同。
static
static 表示静态或者全局,可以用来修饰成员变量和成员方法以及代码块。
使用 stati 修饰的成员变量和成员方法独立于该类的任何一个实例化对象,访问时不依赖于该类的对象,而是直接通过类去访问,可以理解为被该类的所有实例对象所共用,所以说是全局的。
package com.bsj;
public class test2 {
private static int id; // 加了static 结果是 10 ;没加 static 结果是 1
public static void main (String[] args) {
test2 test = null;
for (int i = 0;i<10;i++){
test = new test2();
test.id++;
}
System.out.println(test.id);
}
}
static 还可以修饰代码块,被 static 修饰的代码块叫做静态代码块。
static {
System.out.println(1);
}
静态代码块的特点是只执行一次,什么时候执行?当这个类被加载到内存时执行,不需要开发者手动调用会自动执行。
被加载到内存中的类叫做运行时类,静态代码块就是在加载类的时候执行的,因为类只加载一次,所以静态代码块也只执行一次。
继承
什么是继承?
继承是用来描述类之间的关系,即一个类继承(拥有)另外一个类中的属性和方法,被继承的类叫做父类,继承父类的类叫做子类。
继承的基本语法
public class 类名 extends 父类名{
}
package Test;
public class People {
private int id;
private String name;
private int age;
private char gender;
public int getId () {
return id;
}
public void setId (int id) {
this.id = id;
}
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 char getGender () {
return gender;
}
public void setGender (char gender) {
this.gender = gender;
}
}
package Test;
public class Student extends People{
}
package Test;
public class Teacher extends People{
}
Java 中的继承是单继承,也就是说一个子类只能有一个父类。
子类访问父类
创建一个子类对象的时候,会默认先创建一个父类对象,无论是通过有参构造或是无参构造来创建子类对象,都是通过无参构造来创建父类对象的。
可以通过super 关键字让子类创建对象时调用父类的有参构造。
public Student () {
super(1);
System.out.println("通过无参构造创建Student对象");
}
子类可以访问父类的构造方法、普通方法、成员变量,都是通过super 关键字来完成。
构造方法:super()
普通方法:super.方法名(参数列表)
成员变量:super.成员变量名
在子类的构造方法中,可以通过super 访问父类的构造方法和普通方法。
在子类的普通方法中,只能通过super 访问父类的普通方法。
子类的访问权限
访问权限修饰符:public、protected、默认修饰符、private。
权限修饰符 | 同一个类 | 不同包 | 同一个包 | 子类(同包) | 子类(不同包) |
---|---|---|---|---|---|
public | 可以访问 | 可以访问 | 可以访问 | 可以访问 | 可以访问 |
protected | 可以访问 | 不能访问 | 可以访问 | 可以访问 | 可以访问 |
默认修饰符 | 可以访问 | 不能访问 | 可以访问 | 可以访问 | 不能访问 |
private | 可以访问 | 不能访问 | 不能访问 | 不能访问 | 不能访问 |
包:package,用来管理Java文件,一个项目中不可避免出现同名的Java类,为了防止产生冲突,可以把同名的Java类放在不同的包中
包的命名规范:包名由小写字母组成,不能以 . 开头或结尾,可以包含数字,单步能以数字开头,使用 . 来分层。
包的命名方式一般采用网络域名的方向输出,如 com.company.test/com.company.entity
方法重写
子类在继承父类方法的基础上,对父类方法重新定义并覆盖的操作叫做方法重写。
构造方法不能被重写,方法重写的规则:
-
父子类的方法名相同。
-
父子类的方法参数列表相同。
-
子类方法的返回值与父类方法返回值类型相同或者是其子类。
-
子类方法的访问权限步小于父类。
方法重写 VS 方法重载
-
位置:方法重写在子类中对父类方法进行重写,方法重载就是在同一个类中。
-
方法名:方法重写相同,方法重载也相同。
-
参数列表:方法重写相同,方法重载不同。
-
返回值:方法重写相同或是其子类,方法重载没有要求。
-
访问权限:方法重写不能小于父类,方法重载没有要求。
多态
一个事物具有多种表现形态,在 Java 程序中,定义一个方法,在具体的生成环境中根据不同的需求呈现不同的业务逻辑,多态的前提是继承。
package com.bsj2.test;
public class Member {
public void buyBook(){
}
}
package com.bsj2.test;
public class OrdinaryMember extends Member{
public void buyBook(){
System.out.println("普通会员买书打9折");
}
}
package com.bsj2.test;
public class SuperMember extends Member{
public void buyBook(){
System.out.println("超级会员买书打6折");
}
}
package com.bsj2.test;
public class Cashier {
private Member member;
public Member getMember () {
return member;
}
public void setMember (Member member) {
this.member = member;
}
public void settlement(){
this.member.buyBook();
}
}
package com.bsj2.test;
public class Test {
public static void main (String[] args) {
OrdinaryMember ordinaryMember = new OrdinaryMember();
Cashier cashier = new Cashier();
SuperMember superMember = new SuperMember();
cashier.setMember(superMember);
cashier.settlement();
}
}
多态的具体使用有两种形式:
-
定义方法时形参类型为父类,实际调用方法时传入子类类型的参数。
-
定义方法时返回值类型为父类,调用方法时返回子类对象。
以上两种形式的基本原理都是父类引用可以指向子类对象。
public void settlement(Member member){
member.buyBook();
}
Cashier cashier = new Cashier();
OrdinaryMember ordinaryMember = new OrdinaryMember();
cashier.settlement(ordinaryMember);
public Member getMember(String name){
if (name.equals("ordinary")){
return new OrdinaryMember();
}else{
return new SuperMember();
}
}
总结
Java中的封装、继承和多态是面向对象编程中的重要概念,它们分别表示对象的特性和行为。封装、继承和多态是Java语言的三大特性,它们是面向对象编程的重要基础,在实际编程中应该根据需求灵活使用。
- 封装是指将数据的访问权限限制在对象内部,使外部无法直接访问,只能通过对象提供的接口进行访问。封装可以提高代码的安全性和可维护性,同时也可以隐藏实现细节,降低耦合度。
- 继承是指通过一种类与类之间的关系,一个类可以继承另一个类的属性和方法,并且可以添加自己的属性和方法。继承可以提高代码的复用性,同时也可以形成类之间的层次关系。
- 多态是指同一种类型的对象,在不同的情况下表现出不同的行为。多态可以提高代码的灵活性和扩展性,同时也可以实现接口的统一和代码的简化。