面向对象语言特征
封装、继承、多态。
封装
封装的概念及优点
概念:将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
封装的优点:
只能通过规定的方法进行访问;
隐藏类的实现细节;
方便加入控制语句;
方便修改实现。
具体表现:
属性使用private(私有权限)修饰;
方法使用public(公共权限)修饰。
示例:
public class Demo{
private String name;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
this关键字
概念:代表自身类的对象(当前正在调用这个方法的对象)。
作用范围:使用this关键字引用成员变量;
使用this关键字引用成员方法。
注意:this关键字必须放在非静态的方法内。
代码示例—封装类:
//封装
public class fengzhuang {
//使用private权限修饰符,只能通过规定方法访问
private String name;
private int age;
//通过public权限修饰符修饰方法,对属性进行控制
public void setName(String name){//存
this.name = name;
}
public String getName(){//取
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
代码示例—main方法测试:
//对fengzhuang类中的方法进行测试
public class fztest {
public static void main(String[] args) {
fengzhuang fz = new fengzhuang();
fz.setName("Jim");
fz.setAge(20);
System.out.println(fz.getName());
System.out.println(fz.getAge());
}
}
继承
继承是面向对象程序设计不可缺少的设计思想,是实现代码可重用的基础,是提高代码可扩展性的主要途径。
继承的使用
继承是从已有的类中派生出新的类,新的类能吸收已有类的属性和行为,并能扩展新的能力。
在Java中使用extends关键字来表示继承关系;
Java不支持多继承,单继承使Java的继承关系很简单,一个类只能有一个直接父类;
继承之后子类可以调用父类的所有非私有属性和非私有方法。
继承是代码重用的一种方式。
使用继承的条件:
1.符合is - a关系的设计,使用继承。(is-a关系即什么是什么,如:狗是动物,狗为子类,动物为父类)
2.将子类共有的属性放在父类。
继承的语法格式
[访问权限修饰符][修饰符] 子类名 extends 父类名{ 子类体 }
继承的传递性
1.C类从B类继承,B类又从A类继承,那么C类就具有B类和A类的所有非私有属性和非私有方法。
2.当一个类没有继承任何一个类时,jvm会默认让类继承Object类,Object是java为所有类提供的基类。
示例
public class Animal{
public void eat(){}
}
public class Dog extends Animal{
public void play(){}
}
/*
子类对象可以直接调用父类的方法,强调复用性
Dog dog = new Dog();
dog.eat();
*/
继承中的构造方法
子类构造方法总是先调用父类的构造方法,默认情况下,调用父类的无参构造方法;
可以在子类构造方法的第一行,使用super关键字调用父类任意一个构造方法;
如果使用super,必须写在方法的第一句;
如果子类的构造方法中没有显式地调用基类的构造方法,则系统默认调用基类无参数的构造方法;
原因:子类创建之后需要调用父类的方法,所以在创建子类对象时父类也需要被同时创建。
super关键字
super关键字代表父类的引用,在程序中主要的用途:
在子类构造方法中要调用父类的构造方法,需要注意:super语句只能出现在子类构造方法的第一行;
用"super.成员变量名"来引用父类成员变量;
用"super.方法名(参数列表)"的方式访问父类的方法;
与this的区别:this通常指代当前对象,super通常指代父类。
方法的重写(Override)
与方法重载(Overload)做以区别。
在子类中根据需要对从父类继承来的方法尽行重写,主要是当父类方法实现不能满足子类需求时对父类进行重写。
方法重写的规则:
方法名相同,参数列表相同;
返回值类型相同;
访问权限修饰符相同;
与父类方法结构相同。
注意:构造方法不能重写!
事例:
@Override //java注解是java中事先定义好的一些注解标签,
//作用于类,属性,方法,用于标记,运行,编译时进行解析检测
public void eat(){
super.eat();
}
多态
同一种事物,在不同时刻表现出不同的状态。
多态存在的要求
要有继承(包括接口的实现)前提条件;
要有重写,在父类中定义一些抽象方法(没有方法实现,抽象类,抽象方法会在下一篇中讲到),只是作为功能定义,子类继承后重写父类中没有实现的方法;
父类引用指向子类对象。
多态的使用
1.当编译期类型是父类,运行期类型是子类时,被称为父类引用指向子类对象。
class Animal{
......
}
class Cat extends Animal{
......
}
class Dog extends Animal {
......
}
Animal x = new Cat() //Animal 的引用指向Cat的对象
2.多态环境下对成员方法的调用。
class Animal{
void show() {
System.out.println(“Anmial");
}
}
class Cat extends Animal{
void show() {
System.out.println(“cat");
}
}
......
Animal x = new Cat()
x.show() //Cat 调用的是子类中的方法
/* 编译看左边,运行看右边 */
3.多态环境下对静态成员方法的调用。
class Animal{
static void show() {
System.out.println(“Animal");
}
}
class Cat extends Animal {
static void show() {
System.out.println(“Cat");
}
}
......
Animal x = new Cat()
x.show() //Animal 调用的是动物类中的静态成员方法
/* 编译和运行都看左边 */
4.多态环境下对成员变量的调用。
class Animal{
int num = 3;
}
class Cat extends Animal {
int num = 4;
}
......
Animal x = new Cat()
x.num; //3 调用的是动物类中的成员变量。
/* 编译和运行都看等号左边 */
/* 变量不存在被子类覆写整个概念,只有方法可以被覆写 */
5.方法参数具有多态性(可以提高代码的扩展性)。
class Animal{
void eat() {}
}
class Cat extends Animal{
void eat() {}
}
class Dog extends Animal{
void eat(){}
}
//方法的形式参数类型是父类类型,而传递的实际参数可以是任意子类的对象
method(Animal animal){
animal .eat();
}
6.向上转型(将子类类型转换为父类类型)
class Animal{
void eat(){ }
}
class Cat extends Animal{
void look() {
System.out.println("看家");
}
}
......
Animal x=new Cat() //向上造型,Cat对象提升到Animal对象
x.eat() //只能使用父类中的方法
x.look() //报错!不能使用子类中的方法
7.向下转型(可以使用子类特有的方法)
class Animal{
void eat(){ }
}
class Cat extendsAnimal{
void look() {
System.out.println("看家");
}
}
......
Animal x=new Cat()
Cat m=(Cat)x; //向下转型
m.eat() ;
m.look();//子父类中的方法都可以使用
instanceof关键字
instanceof就是一个二元运算符,是用来在运行时指出对象是否是特定类的一个实例,instanceof通过返回一个Boolean类型的值来指出这个对象是否是这个特定类或者它的子类的一个实例。
简单的理解为: 大类型 instanceof 小类型。检测大类型中是否包含了小类型。
代码示例—父类(Animal)
//多态---父类,动物类
public abstract class Animal {//abstrac代表抽象,具体内容下节讲
private String type;
public void setType(String type){
this.type = type;
}
public String getType(){
return type;
}
//抽象方法
public abstract void eat();
//成员方法
void show(){
System.out.println("Animals");
}
//静态成员方法
static void play(){
System.out.println("动物玩");
}
// 成员变量
int num = 10;
}
代码示例—子类(Dog)
//多态---子类狗
public class Dog extends Animal {//多态存在三要素---继承
@Override
public void eat() {
System.out.println("狗吃骨头!");
}
void show(){
System.out.println("Dog");
}
// 成员方法
int num = 6;
// 子类特有方法
void speak(){
System.out.println("汪汪汪!");
}
}
代码示例—子类(Cat)
//多态---子类猫
public class Cat extends Animal {//多态存在三要素---继承
@Override
public void eat() {
System.out.println("猫吃鱼!");
}
//静态成员方法
static void play(){
System.out.println("猫玩球");
}
// 成员变量
int num = 5;
// 子类特有方法
void speak(){
System.out.println("喵喵喵!");
}
}
代码示例—主类测试
//多态---测试
public class TestAnimal {
public static void main(String[] args) {
// 父类引用指向子类对象,运行期类型是子类时,被称为父类引用指向子类对象
Animal dongwu = new Cat();
Animal dw = new Dog();
// 只能通过父类引用调用父类方法,运行子类结果
dongwu.setType("猫");
System.out.println(dongwu.getType());//猫
// 多态环境下调用成员方法,调用父类方法,运行子类方法,即编译看左边,运行看右边
dw.show();//Dog
// 多态环境下调用静态成员方法,调用父类方法,运行父类方法(编译和运行都看左边)
dongwu.play();//动物玩
// 多态环境下调用成员变量,变量不存在被子类覆写这一说法,只有方法会被覆写(编译运行都看左边)
System.out.println(dongwu.num);//10
System.out.println(dw.num);//10
// 重写方法的使用
dongwu.eat();
dw.eat();
// 向上转型,只能使用父类中的方法,不能使用子类中的方法,上面的代码都是向上转型的使用
// 向下转换,使用子类的特有方法
if (dongwu instanceof Dog){//instanceof 判断前面引用是否包含着后面的类,
// 这里显然不包含因此会执行else
Dog d = (Dog)dongwu;
d.speak();
}else{
System.out.println("dongwu不包含Dog");//"dongwu不包含Dog"
}
if (dongwu instanceof Cat){//向下转型成功
Cat c = (Cat)dongwu;//将父类引用向下转型为子类引用
c.speak();//喵喵喵!
}else{
System.out.println("dongwu不包含Dog");
}
}
}