java面向对象(中)

面向对象

继承:java的继承是通过extends关键字来实现,实现继承的类被称为子类,被继承的称为父类

语法格式:
修饰符 class SubClass extends SuperClass
{
//类定义部分
}
java的子类不能获得父类的构造器。
public class Fruit    //父类
{
	public double weight;    //父类变量
	public void info()      /父类方法
	{
		System.out.println("我是一个水果! 重"+weight+“g”);
	}
}

public class Apple extends Fruit   //子类继承父类
	{
	public static void main (String[]  args)
	{
		//创建Apple对象
		Apple a = new Apple;
		//Apple 本身没有weight成员变量
		//因为继承了父Fruit的关系,也可以访问Apple对象的weight成员变量
		a.weight = 56;
		//调用Apple对象的info方法;
		a.info();
	}
}

java不支持多继承,但是支持多层继承

  • 换句话说:每个类最多只能有一个直接父类,但可以有无限多个间接父类。

  • 例如:

class Fruit extends Plant{...}		//fruit继承Plant
class Apple extends Fruit{...}		//Apple继承fruit
  • 但如果并未指定这个类的直接父类 则默认 Java.lang.Object这个类为它的父类。(object是所有类的父类)

重写父类方法:有时候子类需要重写父类方法。

  • 做法就是:在子类里重新定义父类的方法。则原本父类的方法将会被覆盖。要求“两同两小一大”原则。 两同:方法名 形参列表相同 两小 :子类方法的返回值硬币父类方法返回值类型更小或者相等,子类方法声明抛出的异常应比父类方法的小或者相等。一大:子类方法的访问权限应比父类方法的访问权限更大或者相等。而且 覆盖方法要么都是类方法 要么都是实例方法
  • 重新调用父类被覆盖的方法。
    • super关键字
    • 用于 :用于调用子类在父类中继成得到的实例变量或者方法。super和tihs也不能够出现在statIic修饰的方法中
    • 格式:super.方法名
    • 当然如果父类的方法访问权限:private 则子类不能访问该方法。也无法重写该方法。
  • 调用父类构造器:
    • super调用;super调用的是父类的构造器 而this调用的同一个类中重载的构造器。但是super调用必须出现的子类构造器的第一行,this也是。
    • 例如:
实例:
class Creature
{
	public Craeature()    //父类无参数构造器  隐式调用
	{
		System.out.println("Creature无参数构造器");
	}
}
class Animal extends Creature
{
	public Animal (String[] args )
	{
		System.out.println("Animal 带一个参数的构造器, "+"该动物的name为“+name);
	}
	public Animal(String name ,int age)
	{
		//this调用重载构造器
		this(name);
		System.out.println("Animal带俩个参数的构造器,"+ "其age为"+age);
	}
}
public class wolf extends Animal
	{
	public wolf()
	{
		//显示调用父类有两个参数的构造器
		super("灰太狼",3);
		System.out.println("wolf无参数构造器");
	}
	public static void main(String[] args )
	{
	new wolf();
	}
}

多态:Java引用类型有两个类型:一个是编译时类型,一个是运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译和运行时类型不一致就会出现多态。即相同变量,调用同一个方法时呈现多种不同的行为特征,这就是多态。

  • 前提:
    • 有继承关系
    • 要有方法重写
    • 要有父类引向子类
  • 格式:
    • fu f = new zi();
例:
  Object p = new person();
通常来讲object是父类 person是子类   p只能调用object里的方法。而不能调用person里的方法。
对象的实例变量不具有多态性。
  • 同一个对象在不同时刻体现出来的不同状态。
  • 多态的前提:
    • A:有继承或者实现关系。
    • B:有方法重写。
    • C:有父类或者父接口引用指向子类对象。
  • 多态的分类:
  • a:具体类多态
				class Fu {}
				class Zi extends Fu {}
				
				Fu f = new Zi();
  • b:抽象类多态
				abstract class Fu {}
				class Zi extends Fu {}
				
				Fu f = new Zi();
  • c:接口多态
				interface Fu {}
				class Zi implements Fu {}
		
				Fu f = new Zi();
  • 多态中的成员访问特点:
    • A:成员变量
      • 编译看左边,运行看左边
    • B:构造方法
      • 子类的构造都会默认访问父类构造
    • C:成员方法
      • 编译看左边,运行看右边
    • D:静态方法
      • 编译看左边,运行看左边
        -多态的好处:
    • A:提高代码的维护性(继承体现)
    • B:提高代码的扩展性(多态体现)
  • 多态的弊端:
    • 父不能使用子的特有功能。
    • 子可以当作父使用,父不能当作子使用。
  • 多态中的转型
    • A:向上转型:从子到父
    • B:向下转型:从父到子 (强转)

引用变量的强制类型转换:

  • 引用变量只能调用其编译时类型的方法。语法:(type)variable
  • 注意:
    • 基本类型之间的转换只能在数值类型之间进行
    • 引用类型之间的转换只能在具有继承关系的两个类型之间进行。

异常:ClassCastException
当一个父类实例转换成子类实例类型,则这个对象必须实际上是子类实例才行(即即时编译为父类运行时类型为子类类型) 否则将在运行时引发ClassCastException异常。

  • instanceof运算符:判断强制转换是否执行成功
例如可以将
String str = (String)objpri;
修改为:
if(objpri instanceof String)
{
String str = (String)objpri;
}
这样可以避免出现异常。
判断objpri是否是 String类 或者其子类 实现类的实例  如果是 返回true 否则返回false。

继承与组合

  • 继承缺点:破坏封装
  • 注意:为了父类有良好的封装性,不会因为继承而被子类随意更改,设计父类映注意以下要点:
    • 1.尽量隐藏父类内部数据,尽量把父类所有的成员变量设置为 private访问类型,不要让子类直接访问父类的成员变量。

    • 2.不要让子类随意访问 修改父类的方法。父类的工具方法都设置为private访问控制符修饰。如果父类的方法要被调用则必须以public来修饰,但又不希望子类重写父类的方法,可以用final修饰。如果希望父类的某个方法被重写 则可以用protected来修饰。

    • 3.尽量不要在父类构造器中调用将要被子类重写的方法。

合适派生子类?

  • 子类需要额外增加属性,而且不仅仅是属性值的改变。
  • 子类需要增加自己独有的行为方式。

初始化块

格式:
修饰符{
//初始化块可执行性代码。。。。。。
}

  • 修饰符:只能是static 使用static修饰的是静态初始化块。
  • 初始化块里可以包含任何可执行性语句,包括变量,调用方法 循环 分支。。。。

java创建对象时,系统先为该对象的所有实例变量分配内存(前提是该类已被加载)接着初始化,顺序:先执行初始化块 在执行构造器的。 当有静态初始化块存在时,则在类初始化阶段就执行静态初始化块。

/*初始化块*/
class Root
{
    static
    {
        System.out.println("Root 静态初始化块");
    }
    {
        System.out.println("Root 普通初始化块");
    }
    public Root()
    {
        System.out.println("Root无参数构造器");
    }
}
class Mid extends Root
{
    static
    {
        System.out.println("Mid静态初始化块");
    }
    {
        System.out.println("Mid普通初始化块");
    }
    public Mid()
    {
        System.out.println("Mid无参数构造器");
    }
    public Mid(String msg)
    {
        this();//this 调用Mid里无参数构造器  同一类里
        System.out.println("Mid的带参数构造器,其参数值"+msg);
    }
}
class Leaf extends Mid
{
    static
    {
        System.out.println("Leaf静态初始化模块");
    }
    {
        System.out.println("Leaf普通初始化模块");
    }
    public Leaf()
    {
        //super调用父类构造器
        super("疯狂java讲义");
        System.out.println("执行Leaf构造器");
    }
}
public  class  Test
{
    public static void main(String[] args)
    {
        new Leaf();
        new Leaf();
    }
}
运行结果:

Root 静态初始化块
Mid静态初始化块
Leaf静态初始化模块

Root 普通初始化块
Root无参数构造器
Mid普通初始化块
Mid无参数构造器
Mid的带参数构造器,其参数值疯狂java讲义
Leaf普通初始化模块
执行Leaf构造器

Root 普通初始化块
Root无参数构造器
Mid普通初始化块
Mid无参数构造器
Mid的带参数构造器,其参数值疯狂java讲义
Leaf普通初始化模块
执行Leaf构造器
由运行结果看出,初始化块的运行顺序是:
静态初始化块--》初始化块--》构造器
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值