java--面向对象基础

类的定义

  面向过程 :是一种以过程为中心的编程思想,实现功能的每一步,都是自己实现的
  面向对象 :是一种以对象为中心的编程思想,通过指挥对象实现具体的功能

  • 类的理解

    • 类是对现实生活中一类具有共同属性和行为的事物的抽象
    • 类是对象的数据类型,类是具有相同属性和行为的一组对象的集合
    • 简单理解:类就是对现实事物的一种描述
  • 类的组成

    • 属性:指事物的特征,例如:手机事物(品牌,价格,尺寸)
    • 行为:指事物能执行的操作,例如:手机事物(打电话,发短信)
  • 类和对象的关系

    • 类:类是对现实生活中一类具有共同属性和行为的事物的抽象
    • 对象:是能够看得到摸的着的真实存在的实体
    • 简单理解:类是对事物的一种描述,对象则为具体存在的事物
类的定义
 public class Student {  //定义一个公共类,都可以访问调用该类
// 属性 : 姓名, 年龄
// 成员变量: 跟之前定义变量的格式一样, 只不过位置发生了改变, 类中方法外
String name;
int age;
// 行为 : 学习
// 成员方法: 跟之前定义方法的格式一样, 只不过去掉了static关键字.
public void study(){
System.out.println("学习");
}
}

  对于一个类来说,有三种成员:属性 field、方法 method、构造器 constructor。 

属性(field 成员变量)

  属性用于定义该类或该类对象包含的数据或者说静态特征属性作用范围是整个类体
  在定义成员变量时可以对其初始化,如果不对其初始化,Java 使用默认的值对其初始化。 

数据类型  默认值
整型  0
浮点型  0.0
字符型 '\u0000'
布尔型 false
所有引用类型 null

属性定义格式:

  [修饰符] 属性类型 属性名 = [默认值] ; 

方法

 方法用于定义该类或该类实例的行为特征和功能实现。方法是类和对象行为特征的抽象。面向对象中,整个程序的基本单位是类,方法是从属于类和对象的。

  [修饰符] 方法返回值类型 方法名(形参列表) {
    // n 条语句
  }

构造方法(构造器 constructor) 

 构造器用于对象的初始化

  

  声明格式: 

    [修饰符] 类名(形参列表){
        //n 条语句
        } 

 构造器 4 个要点:

  • 构造器通过 new 关键字调用!!
  • 构造器虽然有返回值,但是不能定义返回值类型(返回值的类型肯定是本类),不能在构造器里使用 return 返回某个值
  • 如果我们没有定义构造器,则编译器会自动定义一个无参的构造方法。如果已定义则编译器不会自动添加!
  •  构造器的方法名必须和类名一致
/*
   定义一个“点”(Point)类用来表示二维空间中的点(有两个坐标)。要求如下:
 可以生成具有特定坐标的点对象。
 提供可以计算该“点”距另外一点距离的方法。
*/
class Point {  // 定义一个类
    double x, y;  // 属性

    public Point(double _x, double _y) { // 有参构造方法
        x = _x;
        y = _y;
    }

    public double getDistance(Point p) {  //一个成员方法,返回类型为double
        return Math.sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
    }

    public static void main(String[] args) {  // 入口
        Point p1 = new Point(3.0, 4.0);
        Point origin = new Point(0.0, 0.0);
        System.out.println(p1.getDistance(origin));
    }
}

构造方法的重载

   构造方法重载(创建不同用户对象)

构造方法重载(创建不同用户对象)
 public class User {
    int id; // id
    String name; // 账户名
    String pwd; // 密码

    public User() {
    }

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public User(int id, String name, String pwd) { // 构造方法重载
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public static void main(String[] args) {
        User u1 = new User();
        User u2 = new User(101, "小七");  // 使用的是有两个参数的构造方法
        User u3 = new User(100, "张三", "123456"); // 使用的是三个参数的构造方法
    }
}

回顾方法重载:

  •    指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载
  •   多个方法在同一个类中
  •   多个方法具有相同的方法名
  •   多个方法的参数不相同,类型不同或者数量不同

特点:

  1.  类型不同或者数量不同重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式
  2.   重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载 

对象的创建和使用

  创建对象的格式:

    类名   对象名 = new 类名();

  调用成员的格式:

   对象名.成员变量

    对象名.成员方法();

示例代码 : 

类的使用
 public class TestStudent {
    /*
    创建对象的格式:
    类名 对象名 = new 类名();
    调用成员变量的格式:
    对象名.变量名
    调用成员方法的格式:
    对象名.方法名();
    */
    public static void main(String[] args) {
    // 类名 对象名 = new 类名();
    Student stu = new Student();
    // 对象名.变量名
    // 默认初始化值
    System.out.println(stu.name); // null
    System.out.println(stu.age); // 0
    stu.name = "张三";
    stu.age = 23;
    System.out.println(stu.name); // 张三
    System.out.println(stu.age); // 23
    // 对象名.方法名();
    stu.study();
    // com.itheima.object1.Student@b4c966a
    // 全类名(包名 + 类名)
    System.out.println(stu);
        }
}
  

对象内存图

单个对象内存图

多个对象内存图

  总结
多个对象在堆内存中,都有不同的内存划分,成员变量存储在各自的内存区域中,成员方法多个对象共用的一份

JAVA 虚拟机内存模型概念

虚拟机栈(简称:栈)的特点如下:

  1. 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等

  2. JVM 为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等

  3. 栈属于线程私有,不能实现线程间的共享!

  4. 栈的存储特性是“先进后出,后进先出

  5. 栈是由系统自动分配,速度快栈是一个连续的内存空间

堆的特点如下:

  1. 堆用于存储创建好的对象和数组(数组也是对象)

  2. JVM 只有一个堆被所有线程共享

  3. 堆是一个不连续的内存空间分配灵活,速度慢!

  4. 堆被所有的线程所共享,在堆上的区域,会被垃圾回收器做进一步划分,例如新生代、老年代的划分。 

方法区(也是堆)特点如下:

  1. 方法区是 JAVA 虚拟机规范,可以有不同的实现。

    i. JDK7 以前是“永久代”

    ii. JDK7 部分去除“永久代”,静态变量、字符串常量池都挪到了堆内存中

    iii. JDK8 是“元数据空间”和堆结合起来。

  2. JVM 只有一个方法区,被所有线程共享!

  3. 方法区实际也是堆,只是用于存储类、常量相关的信息!

  4. 用来存放程序中永远是不变或唯一的内容。(类信息【Class 对象,反射机制中会重点讲授】、静态变量、字符串常量等)

  5. 常量池主要存放常量:如文本字符串、final 常量值

多个对象指向相同内存图

  总结 :
    当多个对象的引用指向同一个内存空间(变量所记录的地址值是一样的)
    只要有任何一个对象修改了内存中的数据,随后,无论使用哪一个对象进行数据获取,都是修改后的数据。

成员变量和局部变量

成员变量和局部变量的区别

  1. 类中位置不同:成员变量(类中方法外)局部变量(方法内部或方法声明上)
  2. 内存中位置不同:成员变量(堆内存)局部变量(栈内存)
  3. 生命周期不同:成员变量(随着对象的存在而存在,随着对象的消失而消失)局部变量(随着方法的调用而存在,醉着方法的调用完毕而消失)
  4. 初始化值不同:成员变量(有默认初始化值)局部变量(没有默认初始化值,必须先定义,赋值才能使用) 

垃圾回收原理和算法

内存管理

  Java 的内存管理很大程度就是:堆中对象的管理,其中包括对象空间的分配和释放。

  对象空间的分配:使用 new 关键字创建对象即可

  对象空间的释放:将对象赋值 null 即可

垃圾回收过程

  任何一种垃圾回收算法一般要做两件基本事情:

    1. 发现无用的对象

    2. 回收无用对象占用的内存空间。

  垃圾回收机制保证可以将“无用的对象”进行回收。

无用的对象指的就是没有任何变量引用该对象。Java 的垃圾回收器通过相关算法发现无用对象,并进行清除和整理。

垃圾回收相关算法

引用计数法

  堆中的每个对象都对应一个引用计数器,当有引用指向这个对象时,引用计数器加1,而当指向该对象的引用失效时(引用变为 null),引用计数器减 1,最后如果该对象的引用计算器的值为 0 时,则 Java 垃圾回收器会认为该对象是

       无用对象并对其进行回收。优点是算法简单,缺点是“循环引用的无用对象”无法别识别。 

this 关键字

    普通方法中,this 总是指向调用该方法的对象。
    构造方法中,this 总是指向正要初始化的对象。

   this()调用重载的构造方法,避免相同的初始化代码。但只能在构造方法中用,并且必须位于构造方法的第一句
    this 不能用于 static 方法中。
    this 是作为普通方法的“隐式参数”,由系统传入到方法中。 

this的用法详解
 public class TestThis {
    int a, b, c;

    TestThis() {
        System.out.println("正要初始化一个Hello对象");
    }

    TestThis(int a, int b) {
        // TestThis(); //这样是无法调用构造方法的!
        this(); // 调用无参的构造方法,并且必须位于第一行!
        a = a;// 这里都是指的局部变量而不是成员变量
        // 这样就区分了成员变量和局部变量. 这种情况占了this使用情况大多数!
        this.a = a;
        this.b = b;
    }

    TestThis(int a, int b, int c) {
        this(a, b); // 调用带参的构造方法,并且必须位于第一行!
        this.c = c;
    }

    void sing() {
    }

    void eat() {
        this.sing(); // 调用本类中的sing();
        System.out.println("你妈妈喊你回家吃饭!");
    }

    public static void main(String[] args) {
        TestThis hi = new TestThis(2, 3);
        hi.eat();
    }
}

this内存原理

注意 : this代表当前调用方法的引用,哪个对象调用的方法,this就代表哪一个对象

static 关键字 

静态变量/静态方法生命周期和类相同,在整个程序执行期间都有效。它有如下特点:

  为该类的公用变量,属于类,被该类的所有实例共享,在类载入时被初始化。

  static 变量只有一份。

  一般用“类名.类变量/方法”来调用。

  在 static 方法中不可直接访问非 static 的成员。

static 关键字的使用
 public class TestStatic {
    int id; // id
    String name; // 账户名
    String pwd; // 密码
    static String company = "北京xxx"; // 公司名称

    public TestStatic(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public void login() {
        System.out.println(name);
    }

    public static void printCompany() {
        // login();//调用非静态成员,编译就会报错
        System.out.println(company);
    }

    public static void main(String[] args) {
        TestStatic u = new TestStatic(101, "高xx");
        TestStatic.printCompany();
        TestStatic.company = "北京阿里";
        TestStatic.printCompany();
    }
}

静态初始化块 

  构造方法用于对象的普通属性初始化。

 静态初始化块,用于类的初始化操作,初始化静态属性。

  在静态初始化块中不能直接访问非 static 成员。 

static 静态初始化块
 public class TestStatic2 {
    static String company; // 公司名称
    static {
        System.out.println("执行类的初始化工作");
        company = "北京xxx";
        printCompany();
    }

    public static void printCompany() {
        System.out.println(company);
    }

    public static void main(String[] args) {
    }
}

包机制(package、import)

  包(package)相当于文件夹对于文件的作用。用于管理类、用于解决类的重名问题。

 package 的使用有两个要点

  1. 通常是类的第一句非注释性语句。

  2. 包名:域名倒着写即可,便于内部管理类。

com.oracle.test;
com.itbaizhan.gao.test;
com.itbaizhan.gao.view;

  JDK 中的主要包

  导入类 import

    如果要使用其他包的类,需使用 import,从而在本类中直接通过类名来调用,否则就需要书写类的完整包名和类名。 

   Java 会默认导入 java.lang 包下所有的类,因此这些类我们可以直接使用。
     如果导入两个同名的类,只能用包名+类名来显示调用相关类:
     java.util.Date date = new java.util.Date()

  静态导入

    静态导入(static import): 其作用是用于导入指定类的静态属性和静态方法,这样我们可以直接使用静态属性和静态方法。

    

静态导入的使用
 package com.itbaizhan;

import static java.lang.Math.*;//导入Math类的所有静态属性
import static java.lang.Math.PI;//导入Math类的PI属性

public class Test2 {
    public static void main(String[] args) {
        System.out.println(PI);
        System.out.println(random());
    }
}
posted @ 2022-09-17 22:45  link-零  阅读(38)  评论(0编辑  收藏  举报