03-面向对象编程(一)

1. Java知识图解

2. 面向对象

(1) 面向对象的理解

Q:如何理解面向对象编程呢?

①理解一:人开门

  • 面向过程:人 打开 门

  • 面向对象:

    人{
    打开(门){
    门.开开();
    }
    }
    门{
    开开(){
    从前往后转90度...
    }
    }

②理解二:人把大象装进冰箱

  • 面向过程:1)打开冰箱 2)把大象放进去 3)关闭冰箱

  • 面向对象:

    人{
    打开(冰箱){
    冰箱.开开()
    }
    操作(大象){
    大象.进入(冰箱)
    }
    关闭(冰箱){
    冰箱.合上()
    }
    }
    大象{
    进入(冰箱){}
    }
    冰箱{
    打开(){}
    合上(){}
    }

(2) 类与对象

①关于于类的设计

②类的组成成分

1) 属性(成员变量,Field)

成员变量 vs 局部变量

相同点:

  1. 遵循变量声明的格式: 数据类型 变量名 = 初始化值

  2. 都有作用域

不同点:

  1. 声明的位置的不同 :

    • 成员变量:声明在类里,方法外

    • 局部变量:声明在方法内,方法的形参部分,代码块内

  2. 成员变量的修饰符有四个:

    public private protected 缺省

    局部变量没有修饰符,与所在的方法修饰符相同。

  3. 初始化值:一定会有初始化值。

    • 成员变量:如果在声明的时候,不显式的赋值,那么不同数据类型会有不同的默认初始化值。

      byte short int long >0
      float double ==>0.0
      char ==>空格
      boolean ==>false
      引用类型变量>null
    • 局部变量:一定要显式的赋值。(局部变量没有默认初始化值)

  4. 二者在内存中存放的位置不同:成员变量存在于堆空间中;局部变量:栈空间中

    总结:关于变量的分类:

  5. 按照数据类型的不同:基本数据类型(8种) & 引用数据类型

  6. 按照声明的位置的不同:成员变量 & 局部变量

2) 方法(成员方法,函数,Method):提供某种功能的实现

1) 实例:

public void eat(){//方法体}
public String getName(){}
public void setName(String n){}

2) 关于返回值类型:

  • void:表明此方法不需要返回值

  • 有返回值的方法:在方法的最后一定有return + 返回值类型对应的变量

  • 记忆:void 与 return 不可以同时出现一个方法内。像一对“冤家”。

3) 方法内可以调用本类的其他方法或属性,但是不能在方法内再定义方法!

③面向对象编程的思想的落地法则一

1) 设计并创建类及类的成分 2) 实例化类的对象 3) 通过“对象.属性”或"对象.方法"的形式完成某项功能

④类的初始化的内存解析

1) 内存划分的结构:

  • 栈(stack):局部变量 、对象的引用名、数组的引用名

  • 堆(heap):new 出来的“东西”(如:对象的实体,数组的实体),含成员变量

  • 方法区:含字符串常量

  • 静态域:声明为 static 的变量

2) 理解的基础上,学会基本的创建的类的对象在内存中的运行。

(3) 方法的重载

方法的重载(overload)要求:

  1. 同一个类中

  2. 方法名必须相同

  3. 方法的参数列表不同(①参数的个数不同②参数类型不同)

补充:方法的重载与方法的返回值类型没有关系!

//如下的四个方法构成重载
//定义两个int型变量的和
public int getSum(int i,int j){
return i + j;
}
//定义三个int型变量的和
public int getSum(int i,int j,int k){
return i + j + k;
}
//定义两个double型数据的和
public double getSum(double d1,double d2){
return d1 + d2;
}
//定义三个double型数组的和
public void getSum(double d1,double d2,double d3){
System.out.println(d1 + d2 + d3);
}
//不能与如上的几个方法构成重载
// public int getSum1(int i,int j,int k){
// return i + j + k;
// }
// public void getSum(int i,int j,int k){
// System.out.println(i + j + k);
// }
//以下的两个方法构成重载。
public void method1(int i,String str){
}
public void method1(String str1,int j){
}

(4) 可变个数的形参的方法

可变个数的形参的方法:

  1. 格式:对于方法的形参: 数据类型 ... 形参名

  2. 可变个数的形参的方法与同名的方法之间构成重载

  3. 可变个数的形参在调用时,个数从0开始,到无穷多个都可以。

  4. 使用可变多个形参的方法与方法的形参使用数组是一致的。

  5. 若方法中存在可变个数的形参,那么一定要声明在方法形参的最后。

  6. 在一个方法中,最多声明一个可变个数的形参。

//如下四个方法构成重载
//在类中一旦定义了重载的可变个数的形参的方法以后,如下的两个方法可以省略
// public void sayHello(){
// System.out.println("hello world!");
// }
// public void sayHello(String str1){
// System.out.println("hello " + str1);
// }
//可变个数的形参的方法
public void sayHello(String ... args){
for(int i = 0;i < args.length;i++){
System.out.println(args[i] + "$");
}
//System.out.println("=====");
}
public void sayHello(int i,String ... args){
//public void sayHello(String ... args,int i){
System.out.println(i);
for(int j = 0;j < args.length;j++){
System.out.println(args[j] + "$");
}
}
public void sayHello1(String[] args){
for(int i = 0;i < args.length;i++){
System.out.println(args[i]);
}
}

(5) java的值传递机制

方法的参数传递(重点、难点) 1. 形参:方法声明时,方法小括号内的参数

实参:调用方法时,实际传入的参数的值

  1. 规则:java中的参数传递机制:值传递机制

    1)形参是基本数据类型的:将实参的值传递给形参的基本数据类型的变量

    2)形参是引用数据类型的:将实参的引用类型变量的值(对应的堆空间的对象实体的首地址值)传递给形参的引用类型变量。

典型例题1:

public static void main(String[] args) {
TestArgsTransfer tt = new TestArgsTransfer();
int i = 10;
int j = 5;
System.out.println("i:" + i + " j:" + j);//i : 10 j : 5
// //交换变量i与j的值
// int temp = i;
// i = j;
// j = temp;
tt.swap(i, j);//将i的值传递给m,j的值传递给n
System.out.println("i:" + i + " j:" + j);//i : 10 j : 5
}
//定义一个方法,交换两个变量的值
public void swap(int m,int n){
int temp = m;
m = n;
n = temp;
System.out.println("m:" + m + " n:" + n);
}

使用 swap 方法以后:

典型例题2:

public class TestArgsTransfer1 {
public static void main(String[] args) {
TestArgsTransfer1 tt = new TestArgsTransfer1();
DataSwap ds = new DataSwap();
System.out.println("ds.i:" + ds.i + " ds.j:" + ds.j);
tt.swap(ds);
System.out.println(ds);
System.out.println("ds.i:" + ds.i + " ds.j:" + ds.j);
}
//交换元素的值
public void swap(DataSwap d){
int temp = d.i;
d.i = d.j;
d.j = temp;
System.out.println(d);//打印引用变量d的值
}
}
class DataSwap{
int i = 10;
int j = 5;
}

(6) 面向对象的特征之一:封装性

1) 面向对象的特征一:封装与隐藏

问题:当创建了类的对象以后,如果直接通过"对象.属性"的方式对相应的对象属性赋值的话,可能会出现不满足实际情况的意外,我们考虑不让对象来直接作用属性,而是通过"对象.方法"的形式,来控制对象对属性的访问。实际情况中,对属性的要求就可以通过方法来体现。

2) 面向对象思想的落地法则二:

(封装性的思想)①将类的属性私有化,②提供公共的方法(setter & getter)来实现调用。

3) 四种权限修饰符

  1. 权限从大到小为:public protected 缺省 private

  2. 四种权限都可以用来修饰属性、方法、构造器

  3. 修饰类的话:public 缺省

(7) 构造器(构造函数)

1) 类的第三个成员:构造器(constructor 构造方法) construction CCB ICBC oop constructor:建造者 构造器的作用:①创建对象 ②给创建的对象的属性赋值

  1. 设计类时,若不显式声明类的构造器的话,程序会默认提供一个空参的构造器.

  2. 一旦显式的定义类的构造器,那么默认的构造器就不再提供。

  3. 如何声明类的构造器。格式:权限修饰符 类名(形参){ }

  4. 类的多个构造器之间构成重载

2) 类对象的属性赋值的先后顺序:

  • ①属性的默认初始化

  • ③通过构造器给属性初始化

  • ④通过"对象.方法"的方式给属性赋值

(8) this关键字

this:

  1. 使用在类中,可以用来修饰属性、方法、构造器

  2. 表示当前对象或者是当前正在创建的对象

  3. 当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须添加this来表明该变量时类成员

  4. 在任意方法内,如果使用当前类的成员变量或成员方法可以在其前面添加 this,增强程序的阅读性

  5. 在构造器中使用“this(形参列表)”显式的调用本类中重载的其它的构造器

  6. 5.1 要求“this(形参列表)”要声明在构造器的首行!

  7. 5.2 类中若存在 n 个构造器,那么最多有 n-1 构造器中使用了 this。

    public class TestPerson {
    public static void main(String[] args) {
    Person p1 = new Person();
    System.out.println(p1.getName() + ":" + p1.getAge());
    Person p2 = new Person("BB",23);
    int temp = p2.compare(p1);
    System.out.println(temp);
    }
    }
    class Person{
    private String name;
    private int age;
    public Person(){
    this.name = "AA";
    this.age = 1;
    }
    public Person(String name){
    this();
    this.name = name;
    }
    public Person(String name,int age){
    this(name);
    this.age = age;
    }
    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;
    }
    public void eat(){
    System.out.println("eating");
    }
    public void sleep(){
    System.out.println("sleeping");
    this.eat();
    }
    //比较当前对象与形参的对象的age谁大。
    public int compare(Person p){
    if(this.age > p.age)
    return 1;
    else if(this.age < p.age)
    return -1;
    else
    return 0;
    }
    }

(9) package/import

package:

  • 声明源文件所在的包,写在程序的第一行。

  • 每“.”一次,表示一层文件目录。

  • 包名都要小写。

import:

  • 1) 显式导入指定包下的类或接口

  • 2) 写在包的声明和源文件之间

  • 3) 如果需要引入多个类或接口,那么就并列写出

  • 4) 如果导入的类是 java.lang 包下的,如:System String Math 等,就不需要显式的声明

  • 5) 理解 .* 的概念,比如 java.util.*

  • 6) 如何处理同名类的导入。如:在 util 包和 sql 包下同时存在 Date 类

  • 7) import static 表示导入指定类的 static 的属性或方法

  • 8) 导入 java.lang.* 只能导入 lang 包下的所有类或接口,不能导入 lang 的子包下的类或接口

//import java.util.Scanner;
//import java.util.Date;
//import java.util.List;
//import java.util.ArrayList;
import java.lang.reflect.Field;
import java.util.*;
import static java.lang.System.*;
public class TestPackageImport {
public static void main(String[] args) {
out.println("helloworld");
Scanner s = new Scanner(System.in);
s.next();
Date d = new Date();
List list = new ArrayList();
java.sql.Date d1 = new java.sql.Date(522535114234L);
Field f = null;
}
}