Core Java学习笔记(二)--类与对象

面向对象(OOP)概述

  1. 面向过程:分析出解决问题所需要的步骤
  2. 面向对象:Java是完全面向对象的语言,Java程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分;只要对象能够满足要求,不关心其功能的具体实现 三大特性:封装、继承、多态
  3. 区别:举例

什么是类与对象?

  1. 类与对象:类是对象的模板,对象是类的一个个体(实例)
    • 类:对某一类事物的描述,抽象的、概念上的定义
    • 对象:实际存在的该类事物的个体,也称为实例
  2. 类之间的关系:
    • 依赖:uses-a,一个类的方法操纵另一个类的对象,应尽量降低类之间的耦合
    • 聚合:has-a,类A的对象包含类B的对象
    • 继承:is-a,特性与共性
  3. 定义类 & 对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Employee {           //定义Employee类 = 属性 + 方法
    String name; //定义属性(成员变量)
    double salary;
    public void info() { //方法:输出name & salary
    System.out.println("姓名:" + name + ";薪资:" + salary);
    }
    }
    //一个类定义完成,仅仅是概念上的定义,抽象的,必须产生对象
    public class EmployeeTest {
    public static void main(String[] args) {
    Employee emp = new Employee(); //创建对象并实例化
    emp.name = "张三"; //访问属性:对象名称.属性
    emp.salary = 6666;
    emp.info(); //访问方法:对象名称.方法
    }
    }

构造方法

  1. 要想使用对象,必须先构造对象;在对象实例化时就会调用构造方法;
  • 构造方法的名称必须与类名称一致;
  • 构造方法的声明处不能有任何返回值类型的声明
  • 不能再构造方法中使用return返回一个值
  • 如果没有自定义构造方法,则自动生成一个构造方法public 类名(){};如果定义了一个构造方法,不管该构造方法是否有参数,都不会生成默认的构造方法。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class Employee {           
    String name;
    double salary;
    public Employee(double s) {
    this.salary = s;
    System.out.println("姓名:" + name + ";薪资:" + salary);
    }
    }

    public class ConstructorTest {
    public static void main(String[] args) {
    System.out.println("声明对象:Employee emp = null;");
    Employee emp = null;
    System.out.println("emp = new Employee(6666);");
    emp = new Employee(6666); //实例化才调用构造方法
    }
    }
  1. 构造方法重载与普通方法一样,会根据参数类型、个数、顺序不同调用不同的构造方法

    1
    2


  2. 匿名对象

成员变量 & 局部变量

  1. 成员变量指的是在类里定义的变量;局部变量指的是在方法里定义的变量

    • 成员变量可以被访问控制符及static修饰,局部变量不能被访问控制符及static修饰;两者都可以定义成final常量
    • 成员变量存储在堆,局部变量存储在栈。局部变量的作用域仅限于定义它的方法,在该方法的外部无法访问它。成员变量的作用域在整个类内部都是可见的,所有成员方法都可以使用它。如果访问权限允许, 还可以在类的外部使用成员变量
    • 局部变量的生存周期与方法的执行期相同:当方法执行到定义局部变量的语句时,局部变量被创建;执行到它所在的作用域的最后一条语句时,局部变量被销毁。类的成员变量,如果是实例成员变量,它和对象的生存期相同。而静态成员变量的生存期是整个程序运行期。
    • 成员变量有默认值,基本类型的默认值为 0,复合类型的默认值为null。(被final修饰且没有static的必须显式赋值),局部变量不会自动赋值,所以局部变量在定义后先要赋初值,然后才能使用
    • 局部变量可以和成员变量同名,且在使用时,局部变量具有更高的优先级 不推荐
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      class Variable {
      //成员变量,显示初始化
      public static String name01 = "类变量";
      public String name02 = "实例变量";
      //成员变量,未初始化,new创建实例时默认初始化
      public static String name03;
      public String name04;
      public void info01( ) { //定义方法
      //int i; //局部变量未初始化无法打印
      //System.out.println(i);
      int i = 10; //局部变量初始化
      System.out.println(i); //10
      }
      public void info02( ) {
      String name02 = "我不是实例变量"; //方法中定义同名成员变量
      System.out.println(name02); //我不是实例变量
      System.out.println(this.name02); //实例变量
      }
      }

      public class VariableTest {
      public static void main(String[] args) {
      //未创建实例前,可以调用类变量,无法调用实例变量
      System.out.println(Variable.name01); //类变量
      Variable var = new Variable();
      //实例化后,可以调用实例变量
      System.out.println(var.name02); //实例变量
      //成员变量未初始化,会默认初始化
      System.out.println(Variable.name03); //null
      System.out.println(var.name04); //null
      //实例化后的对象可以调用类变量,会有警告!不推荐!
      System.out.println(var.name01);
      //实例对象可以改变类变量值,不推荐!
      var.name01 = "实例对象改变了类变量";
      System.out.println(var.name01);
      var.info01(); //10
      //System.out.println(i); 定义在方法中的局部变量i出了方法无法访问
      //方法中的局部变量可以与局部变量同名,且优先调用
      var.info02();
      }
      }
  2. Java传递机制:值传递

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    /*
    * 在这里需要对Java的传递机制进行了解:
    * Java总是采用“按值传递”
    *
    * 一些概念:
    * 值传递:函数在调用的时候,传递的参数不是实参本身,而是它的副本(拷贝)
    * 引用传递:函数在调用的时候,传递的参数就是实参本身(的地址)
    */

    public class ParamTest {
    public static void main(String[] args) {
    /*
    * 第一个测试,
    * 调用的tripleValue方法不能够修改原先的数值
    */
    System.out.println("Testing tripleValue:");
    double percent = 10;
    System.out.println("Before: percent = " + percent);
    tripleValue(percent);
    System.out.println("After: percent = " + percent);

    /*
    * 第二个测试,
    * 调用的tripleSalary方法成功的改变了对象。
    * 你可能会奇怪了:
    * Java明明是按值传递,为什么能够改变原来的对象呢?
    * 其实是因为这样的:
    * Java中,对象(类的实例)都是通过引用来访问的,
    * 比如:
    * Object foo = new Object();
    * foo只是一个引用,指向了新创建的这个Object对象
    * 所以你在这里调用tripleSalary的时候,
    * 传进去的harry参数本身就是一个引用了,
    * 调用的方法对其进行拷贝,
    * 得到的临时变量依然是与harry相同的引用,
    * 所以自然就可以修改这个对象的状态了,
    *
    * 详细的说明可以参考这个网址:
    * http://zhi.hu/MBSN
    * 也可以参阅《Core Java Volume I》第122页
    */
    System.out.println("\nTesting tripleSalary:");
    Employee harry = new Employee("Harrt", 50000);
    System.out.println("Before: salary = " + harry.getSalary());
    tripleSalary(harry);
    System.out.println("After: salary = " + harry.getSalary());

    /*
    * 第三个测试,
    * 调用的swap方法并不能交换两个对象:
    * 因为swap内部交换的是其拷贝过来的临时的对象,
    * 而不是实际的对象
    */
    System.out.println("\nTesting swap:");
    Employee a = new Employee("Alice", 70000);
    Employee b = new Employee("Bob", 60000);
    System.out.println("Before: a = " + a.getName());
    System.out.println("Before: b = " + b.getName());
    swap(a, b);
    System.out.println("After: a = " + a.getName());
    System.out.println("After: b = " + b.getName());
    }

    public static void tripleValue(double x) {
    x = 3 * x;
    System.out.println("End of method: x = " + x);
    }

    public static void tripleSalary(Employee x) {
    x.raiseSalary(200);
    System.out.println("End of method: salary = " + x.getSalary());
    }

    public static void swap(Employee x, Employee y) {
    Employee temp = x;
    x = y;
    y = temp;
    System.out.println("End of method: x = " + x.getName());
    System.out.println("End of method: y = " + y.getName());
    }
    }

    class Employee {
    private String name;
    private double salary;

    public Employee(String n, double s) {
    name = n;
    salary = s;
    }

    public String getName() {
    return name;
    }

    public double getSalary() {
    return salary;
    }

    public void raiseSalary(double byPercent) {
    double raise = salary * byPercent / 100;
    salary += raise;
    }
    }

static关键字

  1. 静态域 & 静态方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    /*staic修饰的变量/方法存储在方法区,被所有的对象所共享,它当且仅当在类初次加载时会被初始化。
    而非静态变量/方法是对象所拥有的,在创建对象的时候被初始化,各个对象之间互不影响。*/
    //所有对象都可以调用static公共属性,最好使用类.静态变量/方法来修改
    public class Person {
    String name; //成员变量
    int age;
    static String country; //static修饰的成员变量称为类变量/静态变量

    public void info() {
    System.out.println("name:" + name +",age:" + age +",Country:" + country);
    Person.printInfo(); //非静态方法中可以调用静态变量/方法
    }
    public static void printInfo() { //静态方法
    //System.out.println("name:" + name + ",Country:" + country); 静态方法不能调用非静态属性/方法
    System.out.println("Country:" + country);
    }

    public static void main(String[] args) {
    Person.country = "China"; //静态变量无需创建对象访问
    Person.printInfo();
    Person per1 = new Person();
    per1.name = "张三";
    per1.age = 20;
    per1.info();
    Person per2 = new Person();
    per2.name = "李四";
    per2.age = 22;
    per2.info();
    }
    }


  1. 静态代码块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    class Book {
    public Book(String msg) {
    System.out.println(msg);
    }
    }

    public class Person01 {
    Book book1 = new Book("book1成员变量初始化");
    static Book book2 = new Book("static成员book2成员变量初始化");
    Book book3 = new Book("book3成员变量初始化");
    static Book book4 = new Book("static成员book4成员变量初始化");

    public Person01(String msg) { //构造方法
    System.out.println(msg);
    }
    public static void funStatic() { //static修饰的静态方法
    System.out.println("static修饰的funStatic方法");
    }

    public static void main(String[] args) {
    Person01.funStatic(); //未创建对象前,通过调用类的静态方法,类的静态变量初始化
    Person01 p1 = new Person01("p1初始化"); //静态变量初始化后,new对象不会再次初始化
    }
    }
    /*static成员book2成员变量初始化
    static成员book4成员变量初始化
    static修饰的funStatic方法
    book1成员变量初始化
    book3成员变量初始化
    p1初始化 */
  2. 理解main方法

代码块

普通、构造、静态、同步

0%