JavaSE部分——面向对象(上)
面向对象(上)
类和对象
方法详解
成员变量和局部变量
隐藏和封装
深入构造器
类的继承
多态
继承与组合
初始化块
一、类和对象
类是对象的抽象,对象是类的实例。
类大致有如下作用:(1)定义变量 (2)创建对象 (3)调用类的方法或访问类的类变量
对象大致有如下作用:(1)访问对象的实例变量 (2)调用对象的方法
1、定义类
[修饰符] class类名 { 零个到多个构造器定义... 零个到多个成员变量... 零个到多个方法... }
定义构造器
[修饰符] 构造器名(形参列表) { //由零条到多条可执行性语句组成的构造器执行体 }
定义成员变量
[修饰符] 类型 成员变量名 [= 默认值]
定义方法
[修饰符] 方法返回值类型 方法名(形参列表) { //由零条到多条可执行性语句组成的方法体 }
代码示例
public class Person { // 定义成员变量 public String name; public int age; // 定义方法 public void say(String content) { System.out.println(content); } }
static修饰的成员不能访问没有static修饰的成员。
构造器是一个类创建对象的根本途径,如果一个类没有构造器,这个类通常无法创建实例。如果程序员没有为一个类编写构造器,则系统会为该类提供一个默认的构造器。一旦程序员为一个类提供了构造器,系统将不再为该类提供构造器。
2、对象的产生和使用
// 使用Person类定义一个Person类型的变量 Person p; // 通过new关键字调用Person类的构造器,返回一个Person实例 // 将该Person实例赋给p变量 p = new Person(); // 访问p的name实例变量,直接为该变量赋值 p.name = "张三"; // 调用p的say()方法,声明say()方法时定义了一个形参 // 调用该方法必须为形参指定一个值 p.say("Hello World!"); // 直接输出p的name实例变量,将输出 张三 System.out.println(p.name);
提示:不管是数组还是对象,当程序访问引用变量的成员变量或方法时,是加上是访问该引用变量所引用的数组、对象的成员变量或方法。
3、对象的this引用
- this作为对象的默认引用有两种情形:
(1)构造器中引用该构造器正在初始化的对象
(2)在方法中引用调用该方法的对象
代码示例
public class Dog { public void jump() { System.out.println("执行jump方法"); } public void run() { this.jump(); System.out.println("执行run方法"); } }
static修饰的方法中不能使用this引用
解决成员变量和局部变量重名问题
public class ThisInConstructor { public int foo; public ThisInConstructor() { int foo = 0; this.foo = 6; } public static void main(String[] args) { // 输出6 System.out.println(new ThisInConstructor().foo); } }
二、方法详解
1、参数传递——值传递
public class PrimitiveTransferTest { public static void swap(int a, int b) { // 交换 int temp = a; a = b; b = temp; System.out.println("swap方法里,a的值是" + a + "; b的值是" + b); } public static void main(String[] args) { int a = 6; int b = 9; swap(a, b); System.out.println("交换结束后,变量a的值是" + a + "; 变量b的值是" + b); } }
2、形参个数可变的方法
public class Varargs { // 定义了形参个数可变的方法 public static void test(int a, String... books) { // books被当成数组处理 for (String tmp : books) { System.out.println(tmp); } // 输出整数变量a的值 System.out.println(a); } public static void main(String[] args) { // 调用test方法 test(5, "abc", "123"); System.out.println("-------------------"); //调用test方法时传入一个数组 test(23,new String[] {"123","abc"}); } }
注意:个数可变的形参只能处于形参列表的最后,一个方法中最大只能包含一个个数可变的形参。个数可变的形参本质就是一个数组类型的形参。
3、方法重载
两同一不同:同一个类中方法名相同,参数列表不同。
public class Overload { public void test() { System.out.println("无参数"); } public void test(String msg) { System.out.println("重载的test方法" + msg); } public static void main(String[] args) { Overload o1 = new Overload(); o1.test(); o1.test("hello"); } }
三、成员变量和局部变量
1、成员变量和局部变量是什么
(1)成员变量:类里定义的变量,无需显示初始化,系统会在这个类的准备或创建该类的实例时进行默认初始化
(2)局部变量:方法里定义的变量,除形参之外,都必须显示初始化
注意:
(1)一个方法里不能定义两个同名的方法局部变量,方法局部变量与形参也不能同名
(2)同一个方法只不同代码块局部变量可以同名
(3)如果先定义代码块局部变量,后定义方法局部变量,前面定义的代码块局部变量与后面定义的方法局部变量也可以同名
2、成员变量的初始化和内存中的运行机制
(1)当系统加载类或创建该类的实例时,系统自动为成员变量分配内存空间,并在分配内存空间后,自动为成员变量指定初始值
3、成员变量的初始化和内存中的运行机制
(1)局部变量定义后,必须经过显示初始化后才能使用,系统不会为局部变量执行初始化
四、隐藏和封装
1、理解封装
- 将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问
2、使用访问控制符
- private(当前类访问权限)
- default(包访问权限)
- protected(子类访问权限)
- public(公共访问权限)
JavaBean代码示例
public class Person { // 成员变量 private String name; private int age; // getter和setter方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
规范:每个实例变量都被使用private修饰,提供了public修饰setter和getter方法
3、package、import和import static
- package机制,提供了类的多层命名空间,用于解决类的命名冲突、类文件管理等问题。package语句必须座位源文件的第一条非注释行语句,一个源文件只能指定一个包。
package packageName;
- import可以向某个Java文件中导入指定包层次下某个类或全部类。import语句位于package语句(如果有的话)之后、类定义之前。java.lang包下的所有类不用导入。
- import static语句也放在Java源文件的package(如果有的话)之后、类定义之前。导入静态的成员变量、静态的方法。
- 使用import可以省略写包名,而使用import static则可以连类名都省略。
五、深入构造器
1、使用构造器执行初始化
2、构造器重载
六、类的继承
1、Java里子类继承父类的语法格式如下:
修饰符 class SubClass extends SuperClass { //类定义部分 }
- 构造方法不能继承
2、重写父类的方法
代码示例
class Bird { public void fly() { System.out.println("飞"); } } public class Ostrich extends Bird { // 重写Bird类的fly方法 public void fly() { System.out.println("跑"); } public static void main(String[] args) { Ostrich os = new Ostrich(); os.fly(); } }
两同两小一大:(1)方法名相同、形参列表相同(2)子类方法返回值类型应比父类方法返回值类型更小或相等、子类方法声明抛出的异常应比父类方法声明抛出的异常类更小或相等(3)子类方法的访问权限应比父类方法的访问权限更大或相等。
- 覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法。
- 当子类覆盖了父类方法后,子类的对象将无法访问父类中被覆盖的方法,但可以在子类方法中调用父类中被覆盖的方法,通过super关键字。
- 如果父类方法具有private访问权限,则该方法对其子类是隐藏的,因此其子类无法访问该方法,也就是无法重写该方法。
- 如果子类中定义了一个父类private方法具有相同的方法名、相同的形参列表、相同的返回值类型的方法,依然不是重写,只是在子类中重新定义了一个新方法
3、super
- super是Java提供的一个关键字,用于限定该对象调用它从父类继承得到的实例变量或方法。
- super也不能出现在static修饰的方法中。
4、调用父类构造器
- 创建子类对象的时候会调用父类的构造方法一次。
七、多态
- 编译事类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。
1、多态性
2、引用变量的强制类型转换
- 只能在具有继承关系的两个类型之间进行,如果是两个没有任何继承关系的类型,则无法进行类型转换,否则编译时就会出现错误。
- 通过instanceof运算符来判断是否可以成功转换。
- 向上转型:子类对象赋给父类引用变量
- 强制类型转换:父类对象赋给子类引用变量
八、继承与组合
P153