Java面向对象特征介绍

面向对象不仅仅在java中有体现,在C++中也有。Java面向对象三大特征

  • 封装和隐藏
  • 继承
  • 多态

1.封装和隐藏

Java中通过将数据声明为private私有,再提供公共(public)的方法,getXXX和setXXX给外部使用,实现对类属性的操作,以期达到以下目的:

  1. 隐藏一个类中不需要对外部提供的实现细节
  2. 调用者只能通过公共方法来实现对属性的访问和操作,以限制对属性的非法或者不合理的操作
  3. 便于修改和维护,增加其可维护性

1.1属性函数设置

对于设置setXXX和getXXX在eclipse IDE中,有较为方便的方法,如下:

public class Person {
    int age;
    String name;
    int sex;
}

选中数据属性,右键/source/Generate Getters and Setters ,勾选需要生成对应方法的属性

public class Person {
    public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getSex() {
		return sex;
	}
	public void setSex(int sex) {
		this.sex = sex;
	}
	int age;
    String name;
    int sex;
}

 即可生成对应的属性方法。

1.2.this关键字

自动生成的属性方法中有一个this关键字,Java中this的作用和其含义有点像,具体使用如下:

  1. 在方法内部使用时,即表示这个方法所属对象的引用
  2. 在构造器中使用时,表示该构造器正则初始化的对象
  3. this便是当前对象,即就是表示调用当前方法,构造方法,属性的对象,如上例中,如果有
    Person p = new Person();
    p.setAge(10);
    

    this.age = age;等价于p.age = age;

  4. 如果是调用构造函数,则必须放置在第一行

如类Person开始没有写构造函数,此时会系统会提供一个无参的默认构造函数,但是如果添加一个带有参数的构造函数,则系统不会再调用默认的构造函数,要想使用必须手动添加一个无参的构造函数。eclipse中提供了快捷的方法,按下Alt+/选择就会生成构造函数。

	public Person(int age,String name,int sex) {
		this();//必须放置在首行
		this.age = age;
		this.name = name;
		this.sex = sex;
		// TODO Auto-generated constructor stub
	}
	public Person() {
		// TODO Auto-generated constructor stub
		System.out.println("调用了默认的构造函数");
	}

 因此,需要注意以下内容:

  • Java每个类至少有一个构造函数
  • 默认构造函数的修饰符与所属类的修饰符一致
  • 一旦显示定义了构造函数,则系统不会提供默认的构造函数
  • 一个类可以创建多个重载的构造函数
  • 父类的构造函数不能被子类继承

2.继承

定义一个父类为Person,描述信息又姓名,年龄等信息

 现在有一个学生类,也有姓名和年龄,且存在一个子类是is-a父类的关系

 

当然还有一个工人类,教师类,程序员类等

 

 这样就形成了一个继承关系,继承关系是面向对象程序中关键特征之一,这里不再介绍关系。Java中继承使用的extends关键字.

注意:子类不是父类的子集,而是父类的扩展,简单的理解就是“青出于蓝而胜于蓝”,且Java中一个子类只能派生于一个父类,就像一个汉字只有一个父亲一样。

2.1.方法的重新override

在子类中可以根据需要对从父类中继承来的方法进行改造,也称之为方法的重置、覆盖。在程序执行时,子类的方法会覆盖父类的方法。

  • 重新方法必须和被重写的方法有相同的方法名称、参数类别和返回类型
  • 重新方法不能使用比被重写方法更严格的访问权限
  • 重新和被重写的方法必须同时为static或者非static
  • 子类抛出的异常不能大于父类被重写方法的异常

当然eclipse也提供了重写方法的快速操作方法

	@Override
	public int getAge() {
		// TODO Auto-generated method stub
		return super.getAge();
	}

 选中之后会自动生成重写(override)方法的模板,既然这里使用到了super,下面介绍一下super关键字

2.2. super

在Java中使用super来调用父类中的指定操作:

  • super用于访问父类定义的属性
  • super用于调用父类中的成员方法
  • super可用于在子类的构造方法中调用父类的构造方法,注意必须放置在第一行

注意:如果子类中出现了和父类的同名函数,则可使用super进行区分,且super的追溯不限于父类,可以是租父类

super和this:this代表类对象的引用,super代表父类的内存空间的引用。

既然说到了调用父类构造函数的问题,这里需要有几点必须注意:

  • 子类中所有的构造函数默认都会访问父类中空参数的构造函数
  • 当父类中没有空参数的构造函数时,子类的构造函数必须通过this或者super指定调用本类或者父类中相应的构造函数,且必须放置在第一行
  • 如果子类构造函数没有显式调用父类或者本类的构造函数,且父类中又没有无参的构造函数时,此时编译出错
public class Person {
	
	public Person(int age,String name,int sex) {
		this();
		this.age = age;
		this.name = name;
		this.sex = sex;
		// TODO Auto-generated constructor stub
	}
	public Person() {
		// TODO Auto-generated constructor stub
		System.out.println("调用了默认的构造函数");
	}
}


public class Student extends Person {

	String school;

	public Student(int age,String name,int sex,String sch) {
		// TODO Auto-generated constructor stub
		super(age,name,sex);
		this.school = sch;
	}
	
}

 2.3.简单类对象的实例化过程

Person  p = new Person();

 2.4.子类对象的实例化过程

Student stu = new Student();

3.多态 

多态性是面向对象的中最重要的概念,在Java中有两种体现

  1. 方法的重载:overload重载,同名方法,参数列表不同;override重写,方法体不同
  2. 对象的多态性,可以直接应用在抽象类和接口上

Java的引用变量有两种类型:编译时类型和运行时类型,编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。若编译时类型和运行时类型不同,则出现多态。

如何区分呢?在Student stu = new Student();中,Student stu就认为是编译时类型,后面的new Student()理解为运行时类型。所所以上面的出现 “多态”就是对象的多态。

		Student stu = new Student();
		
		Person p = new Person();
	
        //父类的引用对象指向子类的实例
		Person e  = new Student();

那如果是下面的场景呢?当前引用对象p引用的是哪个实例?

p = new Student();

当然是指向Student的实例

因为是子类可以看成是特殊的父类,所以父类对象的引用可以指向子类的对象,这就是向上转型(子类的对象可以给父类类型的变量引用) 

注意:一个引用类型的变量如果声明为父类类型,但实际引用的是子类对象,那么该变量就不能访问子类中添加的属性和和方法

		Person p = new Person();
	
        //父类的引用对象指向子类的实例
		Person e  = new Student();
		
		e.school = "school";//非法

 因为属性是在编译时确定的,编译时e为Person类,没有school属性,所以编译会报错

那方法调用呢?

public class Person {
	
	int age;
    String name;
    int sex;
	
	public void showInfor() {
		System.out.println("调用Person中的shwoInfo");
	}
	
}
public class Student extends Person {

	String school;
	
   @Override
	public void showInfor() {
		// TODO Auto-generated method stub
//		super.showInfor();
	   System.out.println("调用Student中的shwoInfo");
	}
	
	public static void main(String[] args) {
		Student stu = new Student();
		stu.showInfor();
		
		Person p = new Person();
	    p.showInfor();
		
        //父类的引用对象指向子类的实例
		Person e  = new Student();
        e.showInfor();//此时e.showInfor会调用哪个类的方法呢?
				
	}
}

输出结果结果为:

调用Student中的shwoInfo
调用Person中的shwoInfo
调用Student中的shwoInfo

这个就是虚拟方法调用

方法调用是在运行的时候确定的,所以调用的是Student类的方法,也就是动态绑定

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值