面向对象(Java)

面向对象(Java)

一、概念

1.首先,我们要了解面向对象,必须要了解第一件事情,java面向对象说:万事万物皆对象
2.我们认知对象,是通过自己对这个世界的统一认识出发的。其中包括提前对于某个对象归属于那个类型的定义
比如说,当我们看到一个手机,由于这个手机符合我们对手机类型的全定义,所以我交这个东西叫手机
3.而我们创建一个相似对象的分类时,使用的“工具”叫做抽象,就是描述着一类对象的名词,当做对象的属性,
将描述这一类对象的动词,当做方法来提取一个模板,任何符合这个模板定义的对象都属于这个类型的对象
4.这个模板,在java中,叫做类。而我们说的万事万物皆对象,就是如何用一个类型创建这一个类的对象

java中:对象建立

①、首先的定义一个类,里头有对象抽象出来共有的属性和方法。eg,手机类

//类:是用来描述对象的模板,是通过抽象和封装过程得到的。
public class CellPhone {
	//成员变量:组成类型的变量
	float weight;
	String color;
	String brand;
	int price;
	
	
	//方法   格式:
	//返回值类型 方法名(参数列表){代码块}
	//return 结束方法,返回值
	boolean callNumber(String num) {   //形式参数      ph.callNumber("156165"); //其15..为实际参数·
		System.out.println(num);
		return true;
	}
	

}

②、创建对象:可以赋值,也可以调用方法

       CellPhone ph = new CellPhone();
   	   ph.brand = "小米";
   	   ph.color = "黑色";		
       ph.price = 900;
	   ph.weight = 100.0f;
	   System.out.println(ph.weight);

注意:如果没有赋值,系统会给对象自动有默认值

int -> 0 , float -> 0.0 ,char -> 空格 ,String -> null

null 与 "“的区别:”"代表有一个string对象,只是里头啥都没有,而null就是虚无,什么都没有

二、JAVA的内存

1、Java的内存分为5个部分:
分别是:程序计数器:记录程序当前执行的行数
本地方法栈:记录Native方法的执行流程
虚拟机栈:记录JVM虚拟机的执行流程
堆:保存实际对象的位置
方法区:静态变量和常量以及类模型等内容所在位置

2、虚拟机栈和堆:
虚拟机栈,当我们的程序,开始运行的时候,虚拟机(JVM)就将内存已经分配好了。
这个时候,JVM给我们了一小片空间来记录当前的代码执行在那些方法中,那些属性记录,这些东西都在栈这个空间中。
但是面向对象语言,有一个特别的特征,就是需要对象去操作业务流程,而栈的大小不能满足放置多个对象,所以我们需要将对象放置在堆中。
如果栈里面需要执行的代码,要用到堆里的对象,怎么办?
栈需要记录这个对象在堆里面的位置,并不记录这个对象
什么时候在堆里面创建对象呢?什么时候在栈里面申明引用呢?
我们把JAVA代码中,这一行,拆解一下: Item item = new Item();
这一行,其实是两个动作的简写,分别是声明和赋值:

声明:Item item;当代码在声明时,JVM会在栈中一个叫做栈帧的东西里面创建一个指向空白的引用(就是C语言的指针),这个空白的引用,指向了null

赋值:当我们写了item = new Item();这个动作又能分为两个部分,第一个部分,叫做对象的创建,就是new Item()

new这个关键字,最主要的行为,就是在堆里面划分一片合理的内存空间,用来保存创建的对象。当我们写了 = 号时,这个时候,栈里面的引用就可以和堆里面的内存空间,关联上了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FEPw9zPw-1617612879439)(C:\Users\11141\AppData\Roaming\Typora\typora-user-images\image-20210331201919962.png)]

三、访问控制

访问控制,就是在创建对象以后,这个对象的属性或者方法是否可以被访问到
读取到(有些属性可能你具有,但是别人是获得不到的)
不写访问控制符时,只在包里头可以调用

1、public 公有

可以有公有属性、公有方法

public int height;

public void test(){

}

公有:在项目内任何位置对象都可以访问或调用。

2、private 私有

可以有公有属性、公有方法

private int height;

private void test(){

}

私有:在类外面无法调用或访问,只可以在类中自己用,私有方法一般用于简写代码,类中其他方法调用。

3、默认访问控制符(default)

int height;

void test(){

}

表示:可以在包内访问或调用。

4、protected 友元访问

包括继承和同包,继承的时候即使在不同包的时候也可以调用(对象不可调用,只能类中直接调用)

protected void eat() {

}

5、总结:主要是调用范围

public-protected-default-private

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3iPL866n-1617612879443)(C:\Users\11141\AppData\Roaming\Typora\typora-user-images\image-20210401194815063.png)]

四、构造方法

1、方法名与类名一致,大小写敏感
2、方法不能有返回值的描述,void也不可加,加上就不是构造方法了
3、这个方法一般在new这个关键字后调用的,是用来创建这个类的对象的
4、如果我们不写这个方法,那么java会给出一个没有参数,没有方法的默认的构造方法
5、也就是说,任何的类中,都有构造方法

public Hero() {
}

public Hero(String nameString,int currentHP,int maxHP,int attackPoint,int attackDefendPoint) {
	this.attackDefendPoint = attackDefendPoint;
	this.attackPoint = attackPoint;
	this.currentHP = currentHP;
	this.nameString = nameString;
	this.maxHP = maxHP;
}

注:一般情况下私有属性由构造方法定义初值,如上代码,构造方法可以重载,即参数列表需要不同。

构造方法(继承中)

子类构造方法是必须先调用父类的构造方法,super(i)
若父类有无参的构造方法(默认调用),子类就可以不用一定要调用父类的构造方法,即super()
调用有参构造就只运行父类的有参构造
子类构造方法中只能调用一个父类构造方法

 public ClassA {
     
     public ClassA(int i){
         
     }
     
   }

   public ClassB extends ClassA {
       
       public ClassB(int i){
           super(i);
       }
       //必须优先调用父类构造方法,若父类构造方法没有重载,则可以默认为没有参数的构造方法
       //并且只可以调用一个父类构造方法,不能一次调用多个父类构造方法,会造成冲突(优先问题)
       
   }

五、继承(扩展)

java在类中只支持链式继承、单继承(extends后不能有多个类)

关键字为:extends —即扩展

   //例子,以下代码都用这个举例
   public ClassA {
       
   }

   public ClassB extends ClassA {
       
   }

其中ClassA成为父类(基类、超类),ClassB为子类(延展类、sub类)

里氏替换原则

在任何需要父类对象的时候,都可以拿子类对象替换

eg: ClassA a = new ClassB();

子类在继承后可以添加自己特有的属性或方法,所以子类对象在堆里头的空间一定是包括一个父类对象,因此可以拿子类对象替换父类对象。

但声明时还是为父类对象,不可以调用子类中的特有方法,可以通过强转类型来调用,但不建议。

六、重写与重载

1、重载

重载,重载过程是方法名一致,但是方法的参数列表的类型、个数、顺序三个方向考量,是不一致的,这个时候,我们将这两个同名的方法叫做重载。返回类型不可以进行重载,就是必须参数列表不同。即只要在本类中即可重载。

2、重写(override)

子类中重新定义父类中已经定义过的方法的过程叫做重写,重写的英文叫做override

  public ClassA {
       void hehe(){
           
       }
   }

   public ClassB extends ClassA {
       //@Override为注解,是一种编程方式,下面这个注解的作用是告诉编译器,eat这个方法是从父类继承过来的
	//并且在本类中重新实现的,约束在父类中必须要有,不然会报错,可以省略就不约束了。
       @Override
       void hehe(){
          //自动生成的代码块,养成习惯删掉此行注解
		  // TODO Auto-generated method 
           
       }
       
   }

注意:

(1)、重写方法时类型与参数列表都得一致

(2)、重写方法或属性时,要注意访问控制符,子类只能对父类的访问限制往大里变

​ 由小到大:private - default - protected - public

七、this

this 是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针

this 的用法在 Java 中大体可以分为3种:

1.普通的直接引用

这种就不用讲了,this 相当于是指向当前对象本身。

2.形参与成员名字重名,用 this 来区分:

实例

class Person {
    private int age = 10;
    public Person(){
    System.out.println("初始化年龄:"+age);
}
    public int GetAge(int age){
        this.age = age;
        return this.age;
    }
}
 
public class test1 {
    public static void main(String[] args) {
        Person Harry = new Person();
        System.out.println("Harry's age is "+Harry.GetAge(12));
    }
}

运行结果:

初始化年龄:10
Harry's age is 12

可以看到,这里 age 是 GetAge 成员方法的形参,this.age 是 Person 类的成员变量。

八、super

super 可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。

super 也有三种用法:

1.普通的直接引用

与 this 类似,super 相当于是指向当前对象的父类,这样就可以用 super.xxx 来引用父类的成员。

2.子类中的成员变量或方法与父类中的成员变量或方法同名

实例

class Country {
    String name;
    void value() {
       name = "China";
    }
}
  
class City extends Country {
    String name;
    void value() {
    name = "Shanghai";
    super.value();      //调用父类的方法
    System.out.println(name);
    System.out.println(super.name);
    }
  
    public static void main(String[] args) {
       City c=new City();
       c.value();
       }
}

运行结果:

Shanghai
China

可以看到,这里既调用了父类的方法,也调用了父类的变量。若不调用父类方法 value(),只调用父类变量 name 的话,则父类 name 值为默认值 null。

3.引用构造函数

  • super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
  • this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。

实例

class Person { 
    public static void prt(String s) { 
       System.out.println(s); 
    } 
   
    Person() { 
       prt("父类·无参数构造方法: "+"A Person."); 
    }//构造方法(1) 
    
    Person(String name) { 
       prt("父类·含一个参数的构造方法: "+"A person's name is " + name); 
    }//构造方法(2) 
} 
    
public class Chinese extends Person { 
    Chinese() { 
       super(); // 调用父类构造方法(1) 
       prt("子类·调用父类"无参数构造方法": "+"A chinese coder."); 
    } 
    
    Chinese(String name) { 
       super(name);// 调用父类具有相同形参的构造方法(2) 
       prt("子类·调用父类"含一个参数的构造方法": "+"his name is " + name); 
    } 
    
    Chinese(String name, int age) { 
       this(name);// 调用具有相同形参的构造方法(3) 
       prt("子类:调用子类具有相同形参的构造方法:his age is " + age); 
    } 
    
    public static void main(String[] args) { 
       Chinese cn = new Chinese(); 
       cn = new Chinese("codersai"); 
       cn = new Chinese("codersai", 18); 
    } 
}

运行结果:

父类·无参数构造方法: A Person.
子类·调用父类”无参数构造方法“: A chinese coder.
父类·含一个参数的构造方法: A person's name is codersai
子类·调用父类”含一个参数的构造方法“: his name is codersai
父类·含一个参数的构造方法: A person's name is codersai
子类·调用父类”含一个参数的构造方法“: his name is codersai
子类:调用子类具有相同形参的构造方法:his age is 18

从本例可以看到,可以用 super 和 this 分别调用父类的构造方法和本类中其他形式的构造方法。

例子中 Chinese 类第三种构造方法调用的是本类中第二种构造方法,而第二种构造方法是调用父类的,因此也要先调用父类的构造方法,再调用本类中第二种,最后是重写第三种构造方法。

九、Java 抽象类


在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

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

由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。

父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。

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

1、抽象类

在Java语言中使用abstract class来定义抽象类。如下实例:

public abstract class Employee
{
   private String name;
   private String address;
   private int number;
   public Employee(String name, String address, int number)
   {
      System.out.println("Constructing an Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   public double computePay()
   {
     System.out.println("Inside Employee computePay");
     return 0.0;
   }
   public void mailCheck()
   {
      System.out.println("Mailing a check to " + this.name
       + " " + this.address);
   }
   public String toString()
   {
      return name + " " + address + " " + number;
   }
   public String getName()
   {
      return name;
   }
   public String getAddress()
   {
      return address;
   }
   public void setAddress(String newAddress)
   {
      address = newAddress;
   }
   public int getNumber()
   {
     return number;
   }
}

2、继承抽象类

我们能通过一般的方法继承Employee类:

Salary.java 文件代码:

public class Salary extends Employee
{
   private double salary; //Annual salary
   public Salary(String name, String address, int number, double
      salary)
   {
       super(name, address, number);
       setSalary(salary);
   }
   public void mailCheck()
   {
       System.out.println("Within mailCheck of Salary class ");
       System.out.println("Mailing check to " + getName()
       + " with salary " + salary);
   }
   public double getSalary()
   {
       return salary;
   }
   public void setSalary(double newSalary)
   {
       if(newSalary >= 0.0)
       {
          salary = newSalary;
       }
   }
   public double computePay()
   {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
}

尽管我们不能实例化一个 Employee 类的对象,但是如果我们实例化一个 Salary 类对象,该对象将从 Employee 类继承 7 个成员方法,且通过该方法可以设置或获取三个成员变量。

AbstractDemo.java 文件代码:

public class AbstractDemo
{
   public static void main(String [] args)
   {
      Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
      Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
 
      System.out.println("Call mailCheck using Salary reference --");
      s.mailCheck();
 
      System.out.println("\n Call mailCheck using Employee reference--");
      e.mailCheck();
    }
}

以上程序编译运行结果如下:

Constructing an Employee
Constructing an Employee
Call mailCheck using  Salary reference --
Within mailCheck of Salary class
Mailing check to Mohd Mohtashim with salary 3600.0

Call mailCheck using Employee reference--
Within mailCheck of Salary class
Mailing check to John Adams with salary 2400.

3、抽象方法

如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。

Abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。

抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。

public abstract class Employee { private String name; private String address; private int number; public abstract double computePay(); //其余代码 }

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

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

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

如果Salary类继承了Employee类,那么它必须实现computePay()方法:

Salary.java 文件代码:

public class Salary extends Employee
{
   private double salary; // Annual salary
  
   public double computePay()
   {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
 
   //其余代码
}

抽象类总结规定

  • 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
  • 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  • 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
  • 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
    法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。

如果Salary类继承了Employee类,那么它必须实现computePay()方法:

Salary.java 文件代码:

public class Salary extends Employee
{
   private double salary; // Annual salary
  
   public double computePay()
   {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
 
   //其余代码
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值