美文网首页Java程序栈
十七、Java中的类(一)

十七、Java中的类(一)

作者: 一直想上树的猪 | 来源:发表于2018-12-05 16:07 被阅读1次

十六、面向对象VS面向过程中,将大象装进一个冰箱的例子中,我们创建了两个类:大象和冰箱。类包含两部分内容:类的成员方法成员变量(属性)

类的语法

[各种类修饰符 public] class 类名{

//类体 描述的主体部分
}

其中,类名也要做到驼峰命名,以及见名知意、而且首字母必须大写。
类的成员变量的类型,支持Java中所有支持的类型(11种)。

对象

一个类的实体叫做对象。比如:我们定义了一个学生,但是我们在主程序中我们需要几个学生,就需要new几个学生对象,类是不能直接使用的,它必须通过new关键字去内存中申请空间,然后才能在CPU中去进行运算,处理相应的业务逻辑。

概念:

类:对具有特定功能的对象的抽象的描述

对象:类的具体的表现形式,类一个实例。

类和对象的关系

类是描述对象的
对象是类的一个具体的实例

思考:先有对象还是先有类?
1:从编码层面:先有类后有对象
2:从分析层面:先有对象后有类
3:现实世界:先有对象,后有类

类和对象的内存分配图

类和对象的内存分配图

构造方法

构造方法是什么?从代码上,直观地看,是new 后面跟的方法。

构造方法,又被称为构造器。
构造方法的特点:

1:构造方法名与类名同名。
2:构造方法没有返回类型。
3:任何类的内部至少要有一个构造方法,如果没有显式的定义构造方法,那么编译器会帮我们自动生成一个默认的构造方法。
4:默认的构造方法,是空实现的方法,没有参数。无参空实现。
5:如果在一个类的内部,只要显式的定义一个构造方法,那么编译器将不再提供默认的构造方法。
6:构造方法只能通过new 关键字来调用。
7:构造方法用来帮助生成本来的对象,在构造方法的方法体中,一般用来对类的成员进行初始化的工作。
8:一个类的内部的构造方法的个数是没有限制的。

构造方法重载:
构造方法参数列表不同

关于Java源文件和类

一个java 源文件 可以有多个class 。
但是一个java 源文件中 最多只能有一个public 修饰的class

如果一个java 源文件中有一个public 修饰的class ,那么源文件的名字必须有该类的类名一致。

一个源文件中类的名字不能冲突,一个包中class 的名字都不能相同。

局部变量 和 类的成员变量

上面提到了,类的成员中的属性叫做成员变量。那局部变量又是森么呢?
局部变量是业务逻辑代码中,除对象之外的定义的变量。
我们来进行比较:
相同点:
两种类型的变量的类型 只要是java支持的类型即可。
命名规范一致。

不同点:
1:作用域不同,类的成员变量的作用域:整个类(构造方法,成员方法中访问),局部变量作用于变量定义之后,下一个向左大括号之前
2:生命周期不同: 局部变量生命周期依赖于方法,方法结束,局部变量被销毁,成员变量的生命周期依赖于所在的对象,对象被回收了,变量也就被回收了。
3:内存中位置不同:局部变量在栈中分配,成员变量在堆中分配。
4:声明定义的位置不同,局部的在方法内声明定义,成员变量在类的内部,方法的外部声明定义。
5:局部变量必须赋值才能使用,成员变量可以不赋值,创建对象后,系统会对所有的成员变量默认初始化。初始化的规则:整数类型--0 浮点数--0.0 字符--0对应的字符
布尔--false 引用数据类型--null
6:访问的优先级,局部变量的优先级高于类的成员变量。如果一个方法内的局部变量和成员变量的名字相同,那么优先访问局部变量。
7:访问的方式不同:类的成员变量的访问方式:对象调用访问。 局部变量的直接访问。

package com.tinner.oop.test;

Java中有定义规范:源文件要分包管理。
如果源文件在某一个包下,那么该源文件的第一句使用关键字 package 声明,该源文件所在的包(目录)。
每一层 目录都是一个标识符,所以每一层包名必须满足标识符的命名规则。

命名规范:包名全部小写

一般的包名的命名:
使用公司的域名的逆序形式 + 功能模块名

几个关键字

import
如果访问了一个跨包的类,那么可以使用import 关键字,在 package 下面将该类 导入。。(告诉当前类,使用某一个类是在哪一个包下)

如果想将某一个包下的所有的类全部导入,,可以使用 通配符 * 。

例如:
import com.tinner.oop.farmer.*;
就是将com.tinner.oop.farmer包下的所有的类全部导入。

也可以使用 类的全路径名的形式访问其他的包的类:
例如:
com.bjsxt.oop.farmer.Farmer farmer= new com.bjsxt.oop.farmer.Farmer();

jdk 增加的新特性
静态导入
import static java.lang.Math.PI;
this
this 就是对象的引用 当前对象的引用 谁调用这个方法,方法内的this 就是谁

通过这样的机制,实现不同的对象访问同一个方法的时候,可以访问自己对象内的属性

所有的成员方法的内部,访问类的成员变量的时候,前面都隐含了一个 this. 当然可以显式的写出来。

建议如果不是必须的,不要显式的提供 this.

注意:this. 访问的肯定是 本类的成员(成员变量,成员方法)

this 的作用:
1:实现不同的对象访问同一个方法的时候,可以访问自己对象内的属性
2:如果类的成员变量和局部变量名字相同,可以使用this区分。
3:this 还可以在一个构造方法内部 访问本类的其他的构造方法,必须在构造方法的第一句执行

static
static是静态的意思
可以用来修饰成员变量,也可以修饰成员方法。
修饰成员变量:
1:被称为静态的成员变量
2:所有的该类的对象共享该变量,该变量在内存中只有一份,不管创建多少个该类的对象。
3:静态成变员量的生存周期不依赖于任何的对象,依赖于类。
4:在类加载的时候分配的内存空间。
5:静态的成员变量,不建议使用对象去直接访问。而是通过类名来访问。
6:静态的成员变量不是在堆内分配空间,在方法区分配空间。

一般情况下终态变量都被修饰成静态的。因为终态的值只能被读取,不能被修改,在内存中只有一份就好。
例子:
final static int MAX_AGE = 100;

类加载:
Person p = new Person();
Person 类是否被加载?如果没有被加载,那么立即加载Person。将Person 类的字节码信息加载到 方法区中。 一共三步(装载、链接、初始化)在加载的最后一步,对静态的成员变量进行初始化。加载完毕之后,才能创建对应类型的对象。 如果Person类的字节码信息已经加载,那就直接创建对象。

类只加载一次。static 成员也只进行空间分配一次。

static 修饰成员方法:
方法就被成为静态方法。

static 修饰的方法的作用:
1:不依赖于任何的对象,直接使用类名调用,工具方法。直接用类名来调用。静态的成员方法比普通的成员方法通常效率要快一些。
在类中定义的方法,如果能使用局部变量实现,就使用局部变量实现。局部变量的执行销毁效率高于类的成员变量。
2:static 修饰的方法可以用来访问类的静态的其他的成员。

思考:

1:静态方法是否可以访问类的实例变量?
不允许,实例变量依赖于对象,静态方法依赖于类,静态方法可以在没有创建对象的时候就可以被调用,这个时候实例变量还没有被分配空间。
2:静态方法中,是否可以有this?
不允许,this 指的某一个对象的引用,但是静态方法调用的时候对象不一定产生。this不一定存在。
3:类的实例方法中是否可以访问静态成员?
允许,实例方法是对象访问,对象都生成了,类早已经加载完毕,所以静态成员早已经被初始化分配空间,所以访问是安全的。

三种内存区域

java 的内存区域,分成了3部分。

1:栈 stack
存放是局部变量 方法返回,方法内定义的局部变量被回收

2:堆 heap
所有new 出来的对象 ,包括数组 都在堆中分配空间 动态分配空间,效率相对较低。

3:运行数据区(方法区,静态代码区)
都是一些静态(不变的数据+static 修饰的数据)的数据

不变的数据:类的字节码数据。
不同的对象有不同的内存空间,但是不同的对象,如果类型相同,那么共享类内定义的成员方法。

生成一个对象的过程

Person p = new Person();

1:类加载(如果已经加载,就不需要再次加载),对静态成员分配空间(对静态成员变量进行默认初始化,然后进行静态成员变量声明处的赋值)

2:对类的所有的实例变量(非静态的)分配空间,并执行默认初始化,在堆中。

3:执行实例变量声明处的赋值。

4:执行构造方法内的代码。

5:构造方法返回 使用new 关键字将对象的引用带回。

关于指针

在Java中,除了8种数据类型之外,都是引用类型。引用类型作为参数,传递的是 引用(地址)
我们先来看一段代码

package com.tinner.oop.test;
public class TestPoint {
    public static void main(String[] args) {
        Point point = new Point(7, 77);
        point.show();
        changePointValue(point);
        point.show();
    }
    public static void changePointValue(Point p){
        int temp = p.x;
        p.x = p.y;
        p.y = temp;
    }
}
class Point{
    int x,y;
    public Point(int _x,int _y){
        x = _x;
        y = _y;
    }
    public void show(){
        System.out.println("x = " + x + " ; y = "+y);
    }
}

那么这段代码在内存中是怎么运行的?


指针底层

代码块

先来说说类的组成: 方法(实例方法+静态方法) 变量(实例变量+静态变量) 构造方法 代码块(构造块+静态块)

在Java中代码块有三种:
1: 局部代码块(在方法内使用)
作用:限制局部变量的作用域,将局部变量的作用域范围控制的更小。
在方法被执行的时候,局部代码块被执行。

2:构造块 (在类的内部,方法的外部) { }
作用:对类的成员进行一些初始化的工作,和构造方法作用类似。
在生成类的对象的时候,每生成一个对象,构造块被执行一次。

编译之后,构造块内的代码将被放置到 构造方法中去执行。(在构造方法内的其他的代码前)。

3:静态代码块 (在类的内部,方法的外部) static {}
作用:执行在一个程序的生命周期中只初始化一次的工作。还可以对静态成员进行初始化。
在加载类的时候执行静态代码块,而且仅执行一次。

在下面的代码中,列出了三种代码块的区别

package com.tinner.oop.test;
public class TestBlock {
    public static void main(String[] args) {
        TestBlock block = new TestBlock();
        TestBlock block1 = new TestBlock();
    }
    //静态代码块 在类加载的时候执行,类加载只有一次,所以执行静态代码块也只有一次。
    //执行一些静态成员的初始化工作,还有一些在一个程序的生命周期内,只初始化一次的工作。
    static int count;
    int age;
    static
    {
        System.out.println("I am static block!");
        count ++;
    }
    //构造块 对类的成员进行初始化
    {
        System.out.println("I am contructor block!---1");
    }
    public TestBlock() {
        this(1);//访问其他的构造方法,必须在构造方法的第一句
        System.out.println("我是构造方法");
    }
    //构造块
    {
        System.out.println("I am contructor block!---2");
    }
    
    TestBlock(int i){
        //构造块的代码插入的位置
        System.out.println("i==="+i);
    }
}

Java中的权限修饰符及其区别

Java中一共四种权限修饰符,用来修饰类以及成员变量。其体现了Java面向对象的其中之一的思想:封装。
封装就是通过对某一个类的成员的访问权限的控制,达到该类内部的成员对于其他的类是否可见的一个控制。
几个关键字:
public: 公有的。本类、本包、跨包其他类 (项目级别的访问权限)
protected:受保护的。本类、本包、跨包子类。
[default]: 默认的。本类、本包 访问 (包私有)
private: 私有的。只能本类访问。
那么,设计类中,通常这些关键字怎么用呢?
设计类的一些基本思路:

1:类的所有的成员变量,全部私有化 private,如果其他的类需要访问当前类的成员变量,那么提供相应的访问器 getter 和修改器 setter
2:所有的类的成员 的访问权限应该控制到最小。如果有需要扩大被访问的权限,再调整。

工具类一般类中都是静态的方法,不需要被实例化,所以工具类的构造方法都是私有化的。
比如:Math 类。
类的访问权限,有两种:

public : 工程级别的,跨包可以访问(import 才能使用)
默认的-defalut:本包访问。

相关文章

  • 十七、Java中的类(一)

    类 在十六、面向对象VS面向过程中,将大象装进一个冰箱的例子中,我们创建了两个类:大象和冰箱。类包含两部分内容:类...

  • class文件和字节码解析

    讲解了Java类和对象在内存中的表示机制,Java对象是根据Java类创建的,表示一个Java类实例;Java类是...

  • Java Object类

    Object 类位于 java.lang 包中,是所有 Java 类的祖先,Java 中的每个类都由它扩展而来。 ...

  • Java Object类

    Object 类位于 java.lang 包中,是所有 Java 类的祖先,Java 中的每个类都由它扩展而来。 ...

  • java线程池

    1.Java中的ThreadPoolExecutor类 1)Java中的ThreadPoolExecutor类是线...

  • object类

    Object 类位于 java.lang 包中,Java 中的每个类都由它扩展而来。 定义Java类时如果没有显示...

  • Java中的类、怎么调用类

    一、java中的类 创建类文件People.java $ touch People.java People.jav...

  • 一.使用Arrays类操作Java中的数组 Arrays 类是 Java 中提供的一个工具类,在 java.uti...

  • Java类加载器 java面试那些jvm的鬼

    Java类加载器 类加载器(class loader) 用来加载 Java 类到 Java 虚拟机中。Java 源...

  • Java 中的数组 使用 Arrays 类操作

    使用 Arrays 类操作 Java 中的数组 Arrays 类是 Java 中提供的一个工具类,在 java.u...

网友评论

    本文标题:十七、Java中的类(一)

    本文链接:https://www.haomeiwen.com/subject/hhkwcqtx.html