《疯狂java讲义》第5章 面向对象(上)

第5章 面向对象(上)

5.1 类和对象

5.1.1 定义类

  • 类(class),对象(object):类是某一批对象的抽象,对象是一个具体的实体。
  • 所有类是引用类型。
//修饰符  class  类名
public class Preson{
	//构造器(可以不写)
	//下面定义两个成员变量
	public String name;
	public int age;
	//下面定义一个say方法
	//修饰符  方法返回值类型  方法名(形参列表)
	public void say (String content){
		System.out.println(content);//方法体
	}
}
  • 构造器:是一个类创建的根本途径,使用new关键字调用构造器时,构造器返回该类的实例。构造器名必须和类名相同(不能定义返回值类型,也不能使用void声明,返回值为总是当前类,是隐式的)(没写时,系统提供默认的构造器)
//使用Person类定义一个Person类型的变量
Person P;
//通过new关键字调用Person类的构造器,返回一个Person实例
//将该Person实例赋给p变量
p = new Person();

Person p = new Person();//简写代码
  • 修饰符:(可以省略)是public,protected,private,static,final,其中public,protected,private三个最多只出现其一,可以与static,final组合起来修饰成员变量。
  • 方法返回值类型:可以是任何数据类型。如果声明了,必须有一个return语句;如果没有返回值,必须使用void来声明没有返回值。
  • static(静态):相当于一个标志,有static修饰的成员属于类本身,没有static修饰的成员属于该类的实例。
  • static修饰的方法和成员变量,即可通过类来调用,也可通过实例来调用;没有static修饰的普通方法个成员变量,只能通过实例来调用。
//访问P的name实例变量,直接为该变量赋值
p.name = "李明";
//调用p的say()方法,声明say()方法时定义了一个形参
p.say("java语言很简单!");
  • 堆内存里的对象可以有多个引用,即多个引用变量指向同一个对象(Person p2 = p)其实为指针类似。

5.1.4 对象的this引用

  • this关键字总是指向调用该方法的对象。作用:让类中的一个方法,访问该类里的另一个方法或实例变量。
  • this作为对象的默认引用有两种情形:构造器中引用该构造器正在初始化的对象;在方法中引用调用该方法的对象。
  • 大多数一个方法访问该类中定义的其他方法、成员变量时加不加this前缀的效果完全一样。(省略this前缀只是一种假象,实际上这个this依然是存在的)
  • static修饰的方法中不能使用this引用。
  • 牢记:java编程时不要使用对象去调用static修饰的成员变量、方法,而是应该使用类去调用static修饰的成员变量、方法。
  • 如果确实需要在静态方法中访问另一个普通方法,则只能重新创建一个对象。
  • 如果构造器中有一个与成员变量同名的局部变量,又必须在构造器中访问这个被覆盖的成员变量,则必须使用this前缀。
  • 使用this作为方法的返回值可以让代码简洁,但可能造成意义的模糊。(return this)

5.2 方法详解

5.2.1 方法的所属性

  • 方法确实是由传统的函数发展而来的。方法不能独立存在,方法必须属于类或对象。
  • 表面上方法可以被独立执行,实际还是使用this或者类来作为调用者。
  • 有static修饰的方法可以使用类和对象作为调用者来调用;没有static修饰的方法则属于该类的对象,不属于这个类本身。

5.2.2 方法的参数传递机制

  • 形参,实参
  • java里方法的参数传递方式只有一种:值传递(将实际参数值的副本传入方法中,而参数本省不会受到任何影响)。
  • 使用引用变量做参数,实际操作的还是堆内存中的对象,所以做出了改变。
  • 形参个数可变的方法:在最后一个形参的类型后增加三点(…),表示该形参可以接受多个参数值。
  • 个数可变的形参只能处于形参列表的最后,一个方法最多只包含一个。(本质就是一个数组类型的形参)
public static void test(int a,String... books )//定义一个形参可变的方法

5.2.4 递归方法

  • 方法递归:一个方法体内调用它自身。(隐式的循环)
  • 递归一样要向已知方向递归。

5.2.5 方法重载

  • 重载:java允许同一个类里定义多个同名方法,只要形参列表不同就行。
public class Overload{
	public void test(){
		System.out.println("无参数");
	}
	public void test(String msg){
		System.out.println("重载的方法" + msg);
	}
}

5.3 成员变量和局部变量

在这里插入图片描述

class Person{
	//定义一个实例变量
	public String name;
	//定义一个类变量
	public static int eyeNum;
}
  • 类变量的作用域比实例变量的作用域更大。
  • 局部变量出除形参外,都必须显示初始化。
  • 如果方法里的局部变量和成员变量同名,局部变量会被覆盖成员变量(可以在方法中显示指定类名和this作为调用者来访问被覆盖的成员变量)。
  • 程序需要访问类变量时,尽量使用类作为主调,而不要使用对象作为主调。
  • 局部变量不属于任何类和实例,因此它总是保存在其所在方法的栈内存中。

5.4 隐藏和封装

  • 封装:(面向对象三大特征:封装、继承、多态)讲对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类提供的方法来实现对内部信息的操作和访问。(该隐藏的隐藏,该暴露的暴露)
  • 访问控制符:private、default、protected、public。

private(当前类访问权限)
default(包访问权限)
protected(子类访问权限)
public(公共访问权限)

  • 外部类只能有两种访问控制级别:public和默认。
public class Person{
	//使用private修饰成员变量,讲这些隐藏起来
	private String name;
	private int age;
	//提供方法来操作name和age
	public void setName(String name){}
	public String getName(){ return this.name; }
	...
}
  • 类里面每个实例变量都被使用private修饰,并为每个实例变量提供public修饰的setter和getter方法,符合JavaBean规范的类,封装良好的类。
  • 类里面绝大部分成员变量使用private修饰;做其他类的父类,希望被子类重写,用protected修饰;给其他类自由调用的方法使用public修饰。
  • java默认为所有源文件导入java.lang包下的所有类(String、System类无需使用import导入),但前面的数组Arrays类,位于java.util包下,须使用import导入。
  • import static(静态导入):导入指定类的某个静态成员变量、方法。
  • import可以省略写包名,import static可以连类名都省略。

5.5 深入构造器

  • 构造器最大的作用是在创建对象时执行初始化。(java类至少包含一个构造器)
  • 构造器重载:同一个类里面具有多个构造器,其中它们的形参列表不同。
  • 通过this调用另一个重载的构造器并初始化。(this调用只能在构造器中使用,必须作为构造器执行体的第一条语句,系统根据实参调用形参列表所对应的构造器)

5.6 类的继承

  • 继承是面向对象的三大特征之一,实现软件复用的重要手段,java的继承具有单继承的特点,每个子类只有一个直接父类(可以有无限多个间接父类)。
  • java的继承通过extends来实现。
  • java.lang.Object类是所有类的父类,所有的Java对象都可调用。
public Apple extends Fruit{
	...
}
  • 重写父类的方法,这种子类包含与父类同名的方法的现象称为方法重写。
  • 原则:“两同两小一大”。两同:方法名和形参列表相同;两小:子类方法的返回值类型和抛出的异常类比父类方法的小或等;一大:子类方法的访问权限比父类大或等。
  • 覆盖方法和被覆盖方法需同是类方法或同是实例方法(static)。
  • 如果需要在子类方法中调用父类中被覆盖的方法,可以使用super(被覆盖的是实例方法)或者父类类名(被覆盖的是类方法)作为调用者来调用。
  • 如果父类方法中具有private访问权限,则该方法对子类是隐藏的,子类无法访问和重写;但子类中定义一个与父类private方法同名的新方法,依然不是重写。
  • 重载发生在同一个类的多个同名方法之间,重写发生在子类和父类的同名方法之间。
  • super. 作为限定类调用这写被覆盖的实例变量和实例方法。
  • super也不能出现在static修饰的方法中。
  • 创建任何对象总是从该类所在继承树最顶层类的构造器开始执行,然后依次向下执行,最后才执行本类的构造器。

5.7 多态

java引用变量有两个类型:编译时类型,运行时类型。如果这两个不一样,就可能出现所谓的多态。

  • 通过引用变量来访问其包含的实例变量时,系统总是试图访问它编译时类型所定义的成员变量,而不是它运行时类型所定义的成语变量。
//p只能调用Object类的方法,不能调用Person类的方法
Object p = new Person();
  • 引用变量的强制类型转换:基本类型之间的转换只能在数值类型之间进行;引用类型之间的转换只能在具有继承关系的两个类型之间进行。
  • 子类对象赋给父类引用变量时,称为向上转型,总是可以成功的。
  • 父类对象赋给子类引用变量时,需要强制类型转换,而其可能产生异常。
  • instanceof运算符:进行强制类型转换之前,判断前一个对象是否是后一个类的实例,是否可以成功转换,代码更加健壮。
if (objPri instanceof String){
	String str = (Stirng) objPri;
}

5.8 继承与组合

继承是实现类复用的重要手段,但继承破坏了封装,采用组合方式实现复用能提供更好的封装性。

  • 设计父类遵循原则:尽量隐藏父类的内部数据(设置为private);不要让子类随意访问修改父类的方法(外部类调用用public,不让子类重写用final修饰,可以被子类重写但不让其他类自由访问用protected修饰);尽量不要在父类构造器中调用将要被子类重写的方法。
  • 派生出子类的条件:子类需要额外增加属性,不仅仅是改变属性值;子类需要增加自己独有的行为方式。
  • 组合*:是把旧类对象作为新类的成员变量组合进来,用以实行新类的功能。(看书P15页代码例子)
  • 继承“是(is-a)”;组合“有(has-a)”。

5.9 初始化块

  • 初始化块的修饰符只能是static,静态初始化块(比普通的先执行)。
  • 系统总是先调用该类里定义的初试化块。(创建对象时隐式执行,在构造器之前)
  • 初始化块是一个假象,其中的代码会被“还原”到每个构造器中,且位于前面。
  • 静态初始化快不能访问非静态初始化块,不能访问实例变量和实例方法。
  • 系统会上溯到java.lang.Object类初始化,然后向下执行。(总是保证该类的所有父类全部加载并初始化)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值