a.使用new关键字产生对象会调用构造方法_java基础类与对象

1.java是面向对象程序设计 OOP

面向对象程序设计(Object Oriented Programming,OOP)是一种计算机编程架构。OOP的一条基本原则是计算机程序由单个能够起到子程序作用的单元或对象组合而成。OOP达到了软件工程的三个主要目标:重用性、灵活性和扩展性。OOP=对象+类+继承+多态+消息,其中核心概念是类和对象。

1.1 类(class)

一个共享相同结构和行为的对象的集合。类(Class)定义了一件事物的抽象特点。通常来说,类定义了事物的属性和它可以做到的(它的行为)。举例来说,“狗”这个类会包含狗的一切基础特征,例如它的孕育、毛皮颜色和吠叫的能力。类可以为程序提供模版和结构。一个类的方法和属性被称为“成员”。

在java中类(class) 是构造对象的模板或蓝图。由类构造(construct) 对象的过程称为创建类的实例 (instance ).

与类紧密关联的还有另一个概念叫做封装。

封装有两层意思,第一层意思:将数据和操作捆绑在一起,创造出一个新的类型的过程。第二层意思:将接口与实现分离的过程。

从形式上看, 封装不过是将数据和行为组合在一个包中, 并对对象的使用者隐藏了数据的实现方式。对象中的数据称为实例域,也就是我们常说的属性、字段。操纵数据的过程称为方法( method ) 。对于每个特定的类实例(对象)都有一组特定的实例域值。这些值的集合就是这个对象的当前状态( state )。无论何时,只要向对象发送一个消息,它的状态就有可能发生改变。

1.2 对象

对象是指可以对其做事情的一些东西。一个对象有状态、行为和标识三种属性。这三个属性分别对应的如下:

    对象的行为(behavior) — 可以对对象施加哪些操作,或可以对对象施加哪些方法 对象的状态(state ) — 当施加那些方法时,对象如何响应 对象标识(identity ) — 如何辨别具有相同行为与状态的不同对象

同一个类的所有对象实例, 由于支持相同的行为而具有家族式的相似性。对象的行为是用可调用的方法定义的。此外,每个对象都保存着描述当前特征的信息。这就是对象的状态。对象的状态可能会随着时间而发生改变,但这种改变不会是自发的。对象状态的改变必须通过调用方法实现 (如果不经过方法调用就可以改变对象状态,只能说明封装性遭到了破坏)。

1.3 类之间的关系

类与类之间主要存在以下几种关系:

依赖

依赖( dependence ), 即 “ uses-a” 关系, 是一种最明显的、 最常见的关系。例如,User类(用户类)使用 Role类(角色类)是因为 User对象需要访问 Role对象查看用户具有什么角色。但是 Student类不依赖于 Role类, 这是因为 Student对象与角色无关。因此, 如果一个类的方法操纵另一个类的对象,我们就说一个类依赖于另一个类。应该尽可能地将相互依赖的类减至最少。如果类 A 不知道 B 的存在, 它就不会关心 B 的任何改变(这意味着 B 的改变不会导致 A 产生任何 bug )。用软件工程的术语来说,就是 让类之间的耦合度最小。尽量做到低耦合的设计要求。

聚合

聚合(aggregation ), 即“ has-a ” 关系, 是一种具体且易于理解的关系。例如, 一个 User对象包含一些 Student对象。聚合关系意味着类 A 的对象包含类 B 的对象。

继承

继承( inheritance ), 即“ is-a” 关系, 是一种用于表示特殊与一般关系的。例如,Tiger类(老虎类)由 Animals类(动物类)继承而来。在具有特殊性的 Tiger类中包含了一些用于优先处理的特殊方法, 以及一个计算运费的不同方法;而其他的方法, 如会行走、会捕猎等都是从 Animals类继承来的。一般而言, 如果类 A 扩展类 B, 类 A 不但包含从类 B 继承的方法,还会添加一些额外的功能。

2. 用引用操纵对象
2.1对象引用

在java 编程思想中有一句经典的介绍说“一切接对象”,也就是说在java语言中可以将所有都当成对象来处理,但是在操纵的标识符实际上是对象的引用。如下:

 String name;

上面的代码中name直接只用String对象中的方法,如toString()方法会报java.lang.NullPointException空指针错误,因为name 只是创建了一个引用,并没有创建对象,所以一般情况都是在创建引用的时候对其进行初始化,如下:

 String name = "Jack";

上面的这种创建对象的方式是java提供的,只使用与String 对象,还有一种更通用的方式创建对象如下:

 String name = new String("Jack");

这里的这个关键字 new所代表的意思就是创建一个新对象。

对象的引用还存于变量之间,如:

 String name = new Strin("Jack");String userName;userName = name;

通过userName = name,这个操作之后这两个变量都引用了同一个String对象。

2.2 初始化对象引用

初始化这些引用变量,可以在代码中的下列位置进行:

    在定义对象的地方。这意味着它们总是能够在构造器被调用之前被初始化 在类的构造器中 在正要使用这些对象之前,这种方式称为惰性初始化 delayed initialization 使用实例初始化

如下代码中有对应的各种初始化场景介绍:

 public class HelloWord {
           
        String name;    //在定义对象的地方进行初始化    String address = "103 Queen Street";    Student student;    public static void main(String[] args) {
           
        }    public HelloWord(){
           
            //在类的构造器中进行初始化        name = new String("Jack");        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(name).toString());    }    public String getName() {
           
            // 在正要使用这些对象之前进行初始化        if (name == null){
           
                name = "Jessie";        }        return name;    }}
3. 内存分配

在我们的程序运行的时候在程序中流转的数据需要存储,对应有以下几个地方可以存储数据:

寄存器:最快的存储区,位于处理器内部。数量有限且我们无法直接控制。

栈:位于通用 RAM(随机访问存储器)中。栈指针下移,则分配新的内存;若上移,则释放那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。

注意 java的对象引用和基本数据类型都是存储在栈中。

一种通用的内存池,位于 RAM 中,用于存放所有的 Java 对象(new 出来都存在堆中)。堆不同于栈的好处就是:编译器不需要知道存储的数据在堆里存活多长时间。

常量存储

常量值 (指被static修饰的值)通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变

非 RAM 存储

如果数据完全存活于程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。比如流对象和持久化对象。

4. 作用域 scope
4.1什么是作用域

作用域决定了在其内定义的变量名的可见性和生命周期。在 Java、作用域由花括号({})的位置决定。如下:

 if (name == null){
           
    name = "Jessie";}

if所具有的作用域就是在他后面的{}中。

4.2 对象作用域

Java 对象不具备和基本类型一样的生命周期。当用 new 创建一个 Java 对象时,它可以存活于作用域之外。比如:

 public void TestScope(){
           
        String name;    if (4<5){
           
            String userName = new String("张三");        name = userName;    }    System.out.println("name = " +name);}

如上代码中name 在if之外定义,userName在if之内创建,并在其中赋值给了name,userName这个变量的生命周期就只在if的作用域中,但是在外面还是能打印出name的值,这就是因为userName所指向的String对象仍然占据存储空间,虽然我们不能在作用域之外访问这个对象。

Java 有一个垃圾回收器,用来监视 new创建的所有对象,并辨别那些不会被再引用的对象,然后释放这些对象的内存空间。

5. 对象的初始化
5.1 构造方法

构造方法(也叫构造函数),是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造方法 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造方法的重载。

在java中构造方法的命名必须和类名完全相同,普通方法可以和构造方法同名,但是必须带有返回值;

如下代码:

 public class HelloWord {
           
        String name;    //在定义对象的地方进行初始化    String address = "103 Queen Street";    Student student;    public static void main(String[] args) {
           
        }    public HelloWord(){
           
            //在类的构造器中进行初始化        name = new String("Jack");        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(name).toString());    }}

可以看到, 构造方法与类同名且没有返回值。在构造 HelloWord类的对象时, 构造方法会运行,以便将实例域初始化为所希望的状态。

对于构造方法需要注意一下几点:

    构造方法与类同名 每个类可以有一个以上的构造方法 构造方法可以有 0 个、1 个或多个参数 构造方法没有返回值 构造方法总是伴随着 new 操作一起调用
5.2 重载 (@Overload)

如下代码:

 public class HelloWord {
           
        public HelloWord(){
           
            //在类的构造器中进行初始化        name = new String("Jack");        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(name).toString());    }    public HelloWord(String name){
           
            //在类的构造器中进行初始化        this.name = name;        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(this.name).toString());    }}

在上面的代码中HelloWord 类中有两个构造方法,他们主要是在参数上的区别,一个是不带参数,一个带了String 类型的参数。

这种特征叫做重载(overloading) 。如果多个方法(比如, HelloWord构造方法)有相同的名字、 不同的参数,便产生了重载。编译器必须挑选出具体执行哪个方法,它通过用各个方法给出的参数类型与特定方法调用所使用的值类型进行匹配来挑选出相应的方法。如果编译器找不到匹配的参数, 就会产生编译时错误,因为根本不存在匹配, 或者没有一个比其他的更好。这个过程被称为重载解析(overloading resolution)。

除了构造方法具有这种重载的情况,普通方法也可以。

5.3 this 关键字

如下代码:

 public class Student{
           
        public void setSno(String sno) {
           
            this.sno = sno;    }    public String getSname() {
           
            return sname;    }}

在上面的代码中setSno这个方法有两个参数:

    隐式 implict 参数:出现在方法名前的 Student类对象。 在每一个方法中, 关键字 this 表示隐式参数。 显式 explicit 参数:位于方法名后面括号中的参数 sno

在 Java 中, 所有的方法都必须在类的内部定义, 但并不表示它们是内联方法。是否将某个方法设置为内联方法是 Java 虚拟机的任务。即时编译器会监视调用那些简洁、经常被调用、 没有被重载以及可优化的方法。

5.4 java中的初始化代码块

静态初始化块

使用 static定义, 只有当类装载到系统时执行一次,之后不再执行。在静态初始化块中仅能初始化 static修饰的数据成员。

非静态初始化块

非静态初始化块: 在每个对象生成时都会被执行一次, 可以初始化类的实例变量。

代码块执行顺序:

    主调类的静态代码块 对象父类的静态代码块 对象的静态代码块 对象父类的非静态代码块 对象父类的构造函数 对象的非静态代码块 对象的构造函数
6. 访问权限控制
6.1 Java 访问权限修饰词

主要分为以下几种情况:

①包访问权限

如果没有指定访问修饰符, 这部分(类、方法或变量)可以被同一个包中的所有方法访问。包访问权限允许将包内所有相关的类组合起来,以使得它们彼此之间可以轻松的相互使用。

对于继承来说,子类是无法访问父类中具有包访问权限的成员

②public 接口访问权限

标记为 public的部分可以被任意的类使用

③private 私有访问权限

标记为 private的部分只能被定义它们的类使用。等于说是隔离了自己。

④protected 继承访问权限

protected也提供包访问权限,也就是说相同包内的其他类可以访问 protected元素,无法跨包访问。

注意:对于继承来说,所有子类都可以访问父类的 protected元素

6.2 基于类的访问权限

修饰词出现在关键字 class 之前,用来控制某个类的访问权限,如:

 public class Student {
           
        private String sno;    private String sname;}

这个类中的public就是在告诉大家任何程序员写的java代码都能访问到Student类,没有限制。

注意:

    每个 .java 文件(编译单元)只能有一个 public类。这表示每个编译单元都有单一的公共接口。 public类的名称必须与含有该编译单元的文件名一致,包括大小写。 类(内部类除外)的访问权限只能是包访问权限或 public。

如果不希望其他任何人对该类拥有访问权限,可以把所有的构造器都指定为 private,从而阻止任何人创建该类的对象。不过,在该类的 static 成员内部可以创建。

7. static 关键字
7.1静态域 / 静态字段

如果将域定义为 static, 每个类中只有一个这样的域,而每一个对象对于所有的实例域却都有自己的一份拷贝。例如:

 class Test{
           
        private static int sno = 1;    private int id;    public static int getSno{
           
            return nextId; // return static field    }    ...}

现在, 每一个 Test对象都有一个自己的 id域, 但这个类的所有实例将共享一个 sno域。换句话说, 如果有 1000 个 Test类的对象, 则有 1000个实例域 id。但是, 只有一 个静态域 sno。即使没有一个 Test对象, 静态域 sno也存在,它属于类,而不属于任何独立的对象。

static初始化只有在第一次创建 Test对象或者调用 Test.sno 的时候才会调用,在那之后,静态域不会重新初始化。初始化的顺序是首先 static,再是其他非 static 对象。

静态域可直接用类名进行调用,例如:

 System.out.println(Test.sno);
7.2静态常量 static final

静态变量使用得比较少,但静态常量却使用得比较多。例如在 Math类中定义了一个 静态常量:

 public class Math{
           
        public static final double PI = 3.14159265358979323846;    ...}

在程序应用中,可以采用 Math.PI 的形式获得这个常量。无法更改且只初始化一次。

7.3静态方法

静态方法是一种不能向对象实施操作的方法。例如, String 类的 valueOf方法就是一个静态方法。

 public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
           
        public static String valueOf(Object obj) {
           
            return (obj == null) ? "null" : obj.toString();    }}

在运算时,不使用任何 String对象。换句话说,没有隐式的参数。可以认为静态方法是没有 this 参数的方法。

在下面两种情况下使用静态方法:

    方法不需要访问对象状态,其所需参数都是通过显式参数提供(例如:Math.valueOf) 一个方法只需要访问类的静态域(例如:Test.getSno)
**8. 对象的清理

在java中当一个对象不再被引用的时候java 的就会任务这个存储垃圾,java会自动调用垃圾回收机制对其进行处理,在一般情况下我们是不需要手动去处理垃圾回收的事情,但也可以手动进行垃圾回收处理,主要有一下两种方式告诉程序需要进行垃圾回收:

    System.gc(); :告诉垃圾收集器打算进行垃圾收集,而垃圾收集器进不进行收集是不确定的 System.runFinalization(); :强制调用已经失去引用的对象的 finalize方法

1.java是面向对象程序设计 OOP 面向对象程序设计(Object Oriented Programming,OOP)是一种计算机编程架构。OOP的一条基本原则是计算机程序由单个能够起到子程序作用的单元或对象组合而成。OOP达到了软件工程的三个主要目标:重用性、灵活性和扩展性。OOP=对象+类+继承+多态+消息,其中核心概念是类和对象。 1.1 类(class) 一个共享相同结构和行为的对象的集合。类(Class)定义了一件事物的抽象特点。通常来说,类定义了事物的属性和它可以做到的(它的行为)。举例来说,“狗”这个类会包含狗的一切基础特征,例如它的孕育、毛皮颜色和吠叫的能力。类可以为程序提供模版和结构。一个类的方法和属性被称为“成员”。 在java中类(class) 是构造对象的模板或蓝图。由类构造(construct) 对象的过程称为创建类的实例 (instance ). 与类紧密关联的还有另一个概念叫做封装。 封装有两层意思,第一层意思:将数据和操作捆绑在一起,创造出一个新的类型的过程。第二层意思:将接口与实现分离的过程。 从形式上看, 封装不过是将数据和行为组合在一个包中, 并对对象的使用者隐藏了数据的实现方式。对象中的数据称为实例域,也就是我们常说的属性、字段。操纵数据的过程称为方法( method ) 。对于每个特定的类实例(对象)都有一组特定的实例域值。这些值的集合就是这个对象的当前状态( state )。无论何时,只要向对象发送一个消息,它的状态就有可能发生改变。 1.2 对象 对象是指可以对其做事情的一些东西。一个对象有状态、行为和标识三种属性。这三个属性分别对应的如下: 对象的行为(behavior) — 可以对对象施加哪些操作,或可以对对象施加哪些方法 对象的状态(state ) — 当施加那些方法时,对象如何响应 对象标识(identity ) — 如何辨别具有相同行为与状态的不同对象 同一个类的所有对象实例, 由于支持相同的行为而具有家族式的相似性。对象的行为是用可调用的方法定义的。此外,每个对象都保存着描述当前特征的信息。这就是对象的状态。对象的状态可能会随着时间而发生改变,但这种改变不会是自发的。对象状态的改变必须通过调用方法实现 (如果不经过方法调用就可以改变对象状态,只能说明封装性遭到了破坏)。 1.3 类之间的关系 类与类之间主要存在以下几种关系: 依赖 依赖( dependence ), 即 “ uses-a” 关系, 是一种最明显的、 最常见的关系。例如,User类(用户类)使用 Role类(角色类)是因为 User对象需要访问 Role对象查看用户具有什么角色。但是 Student类不依赖于 Role类, 这是因为 Student对象与角色无关。因此, 如果一个类的方法操纵另一个类的对象,我们就说一个类依赖于另一个类。应该尽可能地将相互依赖的类减至最少。如果类 A 不知道 B 的存在, 它就不会关心 B 的任何改变(这意味着 B 的改变不会导致 A 产生任何 bug )。用软件工程的术语来说,就是 让类之间的耦合度最小。尽量做到低耦合的设计要求。 聚合 聚合(aggregation ), 即“ has-a ” 关系, 是一种具体且易于理解的关系。例如, 一个 User对象包含一些 Student对象。聚合关系意味着类 A 的对象包含类 B 的对象。 继承 继承( inheritance ), 即“ is-a” 关系, 是一种用于表示特殊与一般关系的。例如,Tiger类(老虎类)由 Animals类(动物类)继承而来。在具有特殊性的 Tiger类中包含了一些用于优先处理的特殊方法, 以及一个计算运费的不同方法;而其他的方法, 如会行走、会捕猎等都是从 Animals类继承来的。一般而言, 如果类 A 扩展类 B, 类 A 不但包含从类 B 继承的方法,还会添加一些额外的功能。 2. 用引用操纵对象 2.1对象引用 在java 编程思想中有一句经典的介绍说“一切接对象”,也就是说在java语言中可以将所有都当成对象来处理,但是在操纵的标识符实际上是对象的引用。如下:  String name; 上面的代码中name直接只用String对象中的方法,如toString()方法会报java.lang.NullPointException空指针错误,因为name 只是创建了一个引用,并没有创建对象,所以一般情况都是在创建引用的时候对其进行初始化,如下:  String name = "Jack"; 上面的这种创建对象的方式是java提供的,只使用与String 对象,还有一种更通用的方式创建对象如下:  String name = new String("Jack"); 这里的这个关键字 new所代表的意思就是创建一个新对象。 对象的引用还存于变量之间,如:  String name = new Strin("Jack");String userName;userName = name; 通过userName = name,这个操作之后这两个变量都引用了同一个String对象。 2.2 初始化对象引用 初始化这些引用变量,可以在代码中的下列位置进行: 在定义对象的地方。这意味着它们总是能够在构造器被调用之前被初始化 在类的构造器中 在正要使用这些对象之前,这种方式称为惰性初始化 delayed initialization 使用实例初始化 如下代码中有对应的各种初始化场景介绍:  public class HelloWord {    String name;    //在定义对象的地方进行初始化    String address = "103 Queen Street";    Student student;    public static void main(String[] args) {   }    public HelloWord(){        //在类的构造器中进行初始化        name = new String("Jack");        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(name).toString());   }    public String getName() {        // 在正要使用这些对象之前进行初始化        if (name == null){            name = "Jessie";       }        return name;   }} 3. 内存分配 在我们的程序运行的时候在程序中流转的数据需要存储,对应有以下几个地方可以存储数据: 寄存器:最快的存储区,位于处理器内部。数量有限且我们无法直接控制。 栈:位于通用 RAM(随机访问存储器)中。栈指针下移,则分配新的内存;若上移,则释放那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。 注意 java的对象引用和基本数据类型都是存储在栈中。 堆 一种通用的内存池,位于 RAM 中,用于存放所有的 Java 对象(new 出来都存在堆中)。堆不同于栈的好处就是:编译器不需要知道存储的数据在堆里存活多长时间。 常量存储 常量值 (指被static修饰的值)通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变 非 RAM 存储 如果数据完全存活于程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。比如流对象和持久化对象。 4. 作用域 scope 4.1什么是作用域 作用域决定了在其内定义的变量名的可见性和生命周期。在 Java、作用域由花括号({})的位置决定。如下:  if (name == null){ name = "Jessie";} if所具有的作用域就是在他后面的{}中。 4.2 对象作用域 Java 对象不具备和基本类型一样的生命周期。当用 new 创建一个 Java 对象时,它可以存活于作用域之外。比如:  public void TestScope(){    String name;    if (4<5){        String userName = new String("张三");        name = userName;   }    System.out.println("name = " +name);} 如上代码中name 在if之外定义,userName在if之内创建,并在其中赋值给了name,userName这个变量的生命周期就只在if的作用域中,但是在外面还是能打印出name的值,这就是因为userName所指向的String对象仍然占据存储空间,虽然我们不能在作用域之外访问这个对象。 Java 有一个垃圾回收器,用来监视 new创建的所有对象,并辨别那些不会被再引用的对象,然后释放这些对象的内存空间。 5. 对象的初始化 5.1 构造方法 构造方法(也叫构造函数),是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造方法 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造方法的重载。 在java中构造方法的命名必须和类名完全相同,普通方法可以和构造方法同名,但是必须带有返回值; 如下代码:  public class HelloWord {    String name;    //在定义对象的地方进行初始化    String address = "103 Queen Street";    Student student;    public static void main(String[] args) {   }    public HelloWord(){        //在类的构造器中进行初始化        name = new String("Jack");        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(name).toString());   }} 可以看到, 构造方法与类同名且没有返回值。在构造 HelloWord类的对象时, 构造方法会运行,以便将实例域初始化为所希望的状态。 对于构造方法需要注意一下几点: 构造方法与类同名 每个类可以有一个以上的构造方法 构造方法可以有 0 个、1 个或多个参数 构造方法没有返回值 构造方法总是伴随着 new 操作一起调用 5.2 重载 (@Overload) 如下代码:  public class HelloWord { public HelloWord(){        //在类的构造器中进行初始化        name = new String("Jack");        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(name).toString());   }    public HelloWord(String name){        //在类的构造器中进行初始化        this.name = name;        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(this.name).toString());   }} 在上面的代码中HelloWord 类中有两个构造方法,他们主要是在参数上的区别,一个是不带参数,一个带了String 类型的参数。 这种特征叫做重载(overloading) 。如果多个方法(比如, HelloWord构造方法)有相同的名字、 不同的参数,便产生了重载。编译器必须挑选出具体执行哪个方法,它通过用各个方法给出的参数类型与特定方法调用所使用的值类型进行匹配来挑选出相应的方法。如果编译器找不到匹配的参数, 就会产生编译时错误,因为根本不存在匹配, 或者没有一个比其他的更好。这个过程被称为重载解析(overloading resolution)。 除了构造方法具有这种重载的情况,普通方法也可以。 5.3 this 关键字 如下代码:  public class Student{    public void setSno(String sno) {        this.sno = sno;   }    public String getSname() {        return sname;   }} 在上面的代码中setSno这个方法有两个参数: 隐式 implict 参数:出现在方法名前的 Student类对象。 在每一个方法中, 关键字 this 表示隐式参数。 显式 explicit 参数:位于方法名后面括号中的参数 sno 在 Java 中, 所有的方法都必须在类的内部定义, 但并不表示它们是内联方法。是否将某个方法设置为内联方法是 Java 虚拟机的任务。即时编译器会监视调用那些简洁、经常被调用、 没有被重载以及可优化的方法。 5.4 java中的初始化代码块 静态初始化块 使用 static定义, 只有当类装载到系统时执行一次,之后不再执行。在静态初始化块中仅能初始化 static修饰的数据成员。 非静态初始化块 非静态初始化块: 在每个对象生成时都会被执行一次, 可以初始化类的实例变量。 代码块执行顺序: 主调类的静态代码块 对象父类的静态代码块 对象的静态代码块 对象父类的非静态代码块 对象父类的构造函数 对象的非静态代码块 对象的构造函数 6. 访问权限控制 6.1 Java 访问权限修饰词 主要分为以下几种情况: ①包访问权限 如果没有指定访问修饰符, 这部分(类、方法或变量)可以被同一个包中的所有方法访问。包访问权限允许将包内所有相关的类组合起来,以使得它们彼此之间可以轻松的相互使用。 对于继承来说,子类是无法访问父类中具有包访问权限的成员 ②public 接口访问权限 标记为 public的部分可以被任意的类使用 ③private 私有访问权限 标记为 private的部分只能被定义它们的类使用。等于说是隔离了自己。 ④protected 继承访问权限 protected也提供包访问权限,也就是说相同包内的其他类可以访问 protected元素,无法跨包访问。 注意:对于继承来说,所有子类都可以访问父类的 protected元素 6.2 基于类的访问权限 修饰词出现在关键字 class 之前,用来控制某个类的访问权限,如:  public class Student {    private String sno;    private String sname;} 这个类中的public就是在告诉大家任何程序员写的java代码都能访问到Student类,没有限制。 注意: 每个 .java 文件(编译单元)只能有一个 public类。这表示每个编译单元都有单一的公共接口。 public类的名称必须与含有该编译单元的文件名一致,包括大小写。 类(内部类除外)的访问权限只能是包访问权限或 public。 如果不希望其他任何人对该类拥有访问权限,可以把所有的构造器都指定为 private,从而阻止任何人创建该类的对象。不过,在该类的 static 成员内部可以创建。 7. static 关键字 7.1静态域 / 静态字段 如果将域定义为 static, 每个类中只有一个这样的域,而每一个对象对于所有的实例域却都有自己的一份拷贝。例如:  class Test{    private static int sno = 1;    private int id;    public static int getSno{        return nextId; // return static field   }   ...} 现在, 每一个 Test对象都有一个自己的 id域, 但这个类的所有实例将共享一个 sno域。换句话说, 如果有 1000 个 Test类的对象, 则有 1000个实例域 id。但是, 只有一 个静态域 sno。即使没有一个 Test对象, 静态域 sno也存在,它属于类,而不属于任何独立的对象。 static初始化只有在第一次创建 Test对象或者调用 Test.sno 的时候才会调用,在那之后,静态域不会重新初始化。初始化的顺序是首先 static,再是其他非 static 对象。 静态域可直接用类名进行调用,例如:  System.out.println(Test.sno); 7.2静态常量 static final 静态变量使用得比较少,但静态常量却使用得比较多。例如在 Math类中定义了一个 静态常量:  public class Math{    public static final double PI = 3.14159265358979323846;   ...} 在程序应用中,可以采用 Math.PI 的形式获得这个常量。无法更改且只初始化一次。 7.3静态方法 静态方法是一种不能向对象实施操作的方法。例如, String 类的 valueOf方法就是一个静态方法。  public final class String implements java.io.Serializable, Comparable , CharSequence { public static String valueOf(Object obj) {        return (obj == null) ? "null" : obj.toString();   }} 在运算时,不使用任何 String对象。换句话说,没有隐式的参数。可以认为静态方法是没有 this 参数的方法。 在下面两种情况下使用静态方法: 方法不需要访问对象状态,其所需参数都是通过显式参数提供(例如:Math.valueOf) 一个方法只需要访问类的静态域(例如:Test.getSno) **8. 对象的清理 在java中当一个对象不再被引用的时候java 的就会任务这个存储垃圾,java会自动调用垃圾回收机制对其进行处理,在一般情况下我们是不需要手动去处理垃圾回收的事情,但也可以手动进行垃圾回收处理,主要有一下两种方式告诉程序需要进行垃圾回收: System.gc(); :告诉垃圾收集器打算进行垃圾收集,而垃圾收集器进不进行收集是不确定的 System.runFinalization(); :强制调用已经失去引用的对象的 finalize方法
1.java是面向对象程序设计 OOP 面向对象程序设计(Object Oriented Programming,OOP)是一种计算机编程架构。OOP的一条基本原则是计算机程序由单个能够起到子程序作用的单元或对象组合而成。OOP达到了软件工程的三个主要目标:重用性、灵活性和扩展性。OOP=对象+类+继承+多态+消息,其中核心概念是类和对象。 1.1 类(class) 一个共享相同结构和行为的对象的集合。类(Class)定义了一件事物的抽象特点。通常来说,类定义了事物的属性和它可以做到的(它的行为)。举例来说,“狗”这个类会包含狗的一切基础特征,例如它的孕育、毛皮颜色和吠叫的能力。类可以为程序提供模版和结构。一个类的方法和属性被称为“成员”。 在java中类(class) 是构造对象的模板或蓝图。由类构造(construct) 对象的过程称为创建类的实例 (instance ). 与类紧密关联的还有另一个概念叫做封装。 封装有两层意思,第一层意思:将数据和操作捆绑在一起,创造出一个新的类型的过程。第二层意思:将接口与实现分离的过程。 从形式上看, 封装不过是将数据和行为组合在一个包中, 并对对象的使用者隐藏了数据的实现方式。对象中的数据称为实例域,也就是我们常说的属性、字段。操纵数据的过程称为方法( method ) 。对于每个特定的类实例(对象)都有一组特定的实例域值。这些值的集合就是这个对象的当前状态( state )。无论何时,只要向对象发送一个消息,它的状态就有可能发生改变。 1.2 对象 对象是指可以对其做事情的一些东西。一个对象有状态、行为和标识三种属性。这三个属性分别对应的如下: 对象的行为(behavior) — 可以对对象施加哪些操作,或可以对对象施加哪些方法 对象的状态(state ) — 当施加那些方法时,对象如何响应 对象标识(identity ) — 如何辨别具有相同行为与状态的不同对象 同一个类的所有对象实例, 由于支持相同的行为而具有家族式的相似性。对象的行为是用可调用的方法定义的。此外,每个对象都保存着描述当前特征的信息。这就是对象的状态。对象的状态可能会随着时间而发生改变,但这种改变不会是自发的。对象状态的改变必须通过调用方法实现 (如果不经过方法调用就可以改变对象状态,只能说明封装性遭到了破坏)。 1.3 类之间的关系 类与类之间主要存在以下几种关系: 依赖 依赖( dependence ), 即 “ uses-a” 关系, 是一种最明显的、 最常见的关系。例如,User类(用户类)使用 Role类(角色类)是因为 User对象需要访问 Role对象查看用户具有什么角色。但是 Student类不依赖于 Role类, 这是因为 Student对象与角色无关。因此, 如果一个类的方法操纵另一个类的对象,我们就说一个类依赖于另一个类。应该尽可能地将相互依赖的类减至最少。如果类 A 不知道 B 的存在, 它就不会关心 B 的任何改变(这意味着 B 的改变不会导致 A 产生任何 bug )。用软件工程的术语来说,就是 让类之间的耦合度最小。尽量做到低耦合的设计要求。 聚合 聚合(aggregation ), 即“ has-a ” 关系, 是一种具体且易于理解的关系。例如, 一个 User对象包含一些 Student对象。聚合关系意味着类 A 的对象包含类 B 的对象。 继承 继承( inheritance ), 即“ is-a” 关系, 是一种用于表示特殊与一般关系的。例如,Tiger类(老虎类)由 Animals类(动物类)继承而来。在具有特殊性的 Tiger类中包含了一些用于优先处理的特殊方法, 以及一个计算运费的不同方法;而其他的方法, 如会行走、会捕猎等都是从 Animals类继承来的。一般而言, 如果类 A 扩展类 B, 类 A 不但包含从类 B 继承的方法,还会添加一些额外的功能。 2. 用引用操纵对象 2.1对象引用 在java 编程思想中有一句经典的介绍说“一切接对象”,也就是说在java语言中可以将所有都当成对象来处理,但是在操纵的标识符实际上是对象的引用。如下:  String name; 上面的代码中name直接只用String对象中的方法,如toString()方法会报java.lang.NullPointException空指针错误,因为name 只是创建了一个引用,并没有创建对象,所以一般情况都是在创建引用的时候对其进行初始化,如下:  String name = "Jack"; 上面的这种创建对象的方式是java提供的,只使用与String 对象,还有一种更通用的方式创建对象如下:  String name = new String("Jack"); 这里的这个关键字 new所代表的意思就是创建一个新对象。 对象的引用还存于变量之间,如:  String name = new Strin("Jack");String userName;userName = name; 通过userName = name,这个操作之后这两个变量都引用了同一个String对象。 2.2 初始化对象引用 初始化这些引用变量,可以在代码中的下列位置进行: 在定义对象的地方。这意味着它们总是能够在构造器被调用之前被初始化 在类的构造器中 在正要使用这些对象之前,这种方式称为惰性初始化 delayed initialization 使用实例初始化 如下代码中有对应的各种初始化场景介绍:  public class HelloWord {    String name;    //在定义对象的地方进行初始化    String address = "103 Queen Street";    Student student;    public static void main(String[] args) {   }    public HelloWord(){        //在类的构造器中进行初始化        name = new String("Jack");        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(name).toString());   }    public String getName() {        // 在正要使用这些对象之前进行初始化        if (name == null){            name = "Jessie";       }        return name;   }} 3. 内存分配 在我们的程序运行的时候在程序中流转的数据需要存储,对应有以下几个地方可以存储数据: 寄存器:最快的存储区,位于处理器内部。数量有限且我们无法直接控制。 栈:位于通用 RAM(随机访问存储器)中。栈指针下移,则分配新的内存;若上移,则释放那些内存。这是一种快速有效的分配存储方法,仅次于寄存器。 注意 java的对象引用和基本数据类型都是存储在栈中。 堆 一种通用的内存池,位于 RAM 中,用于存放所有的 Java 对象(new 出来都存在堆中)。堆不同于栈的好处就是:编译器不需要知道存储的数据在堆里存活多长时间。 常量存储 常量值 (指被static修饰的值)通常直接存放在程序代码内部,这样做是安全的,因为它们永远不会被改变 非 RAM 存储 如果数据完全存活于程序之外,那么它可以不受程序的任何控制,在程序没有运行时也可以存在。比如流对象和持久化对象。 4. 作用域 scope 4.1什么是作用域 作用域决定了在其内定义的变量名的可见性和生命周期。在 Java、作用域由花括号({})的位置决定。如下:  if (name == null){ name = "Jessie";} if所具有的作用域就是在他后面的{}中。 4.2 对象作用域 Java 对象不具备和基本类型一样的生命周期。当用 new 创建一个 Java 对象时,它可以存活于作用域之外。比如:  public void TestScope(){    String name;    if (4<5){        String userName = new String("张三");        name = userName;   }    System.out.println("name = " +name);} 如上代码中name 在if之外定义,userName在if之内创建,并在其中赋值给了name,userName这个变量的生命周期就只在if的作用域中,但是在外面还是能打印出name的值,这就是因为userName所指向的String对象仍然占据存储空间,虽然我们不能在作用域之外访问这个对象。 Java 有一个垃圾回收器,用来监视 new创建的所有对象,并辨别那些不会被再引用的对象,然后释放这些对象的内存空间。 5. 对象的初始化 5.1 构造方法 构造方法(也叫构造函数),是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造方法 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造方法的重载。 在java中构造方法的命名必须和类名完全相同,普通方法可以和构造方法同名,但是必须带有返回值; 如下代码:  public class HelloWord {    String name;    //在定义对象的地方进行初始化    String address = "103 Queen Street";    Student student;    public static void main(String[] args) {   }    public HelloWord(){        //在类的构造器中进行初始化        name = new String("Jack");        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(name).toString());   }} 可以看到, 构造方法与类同名且没有返回值。在构造 HelloWord类的对象时, 构造方法会运行,以便将实例域初始化为所希望的状态。 对于构造方法需要注意一下几点: 构造方法与类同名 每个类可以有一个以上的构造方法 构造方法可以有 0 个、1 个或多个参数 构造方法没有返回值 构造方法总是伴随着 new 操作一起调用 5.2 重载 (@Overload) 如下代码:  public class HelloWord { public HelloWord(){        //在类的构造器中进行初始化        name = new String("Jack");        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(name).toString());   }    public HelloWord(String name){        //在类的构造器中进行初始化        this.name = name;        // 使用实例时进行初始化(当需要使用Student 这个对象的时候才去初始化)        System.out.println(new Student(this.name).toString());   }} 在上面的代码中HelloWord 类中有两个构造方法,他们主要是在参数上的区别,一个是不带参数,一个带了String 类型的参数。 这种特征叫做重载(overloading) 。如果多个方法(比如, HelloWord构造方法)有相同的名字、 不同的参数,便产生了重载。编译器必须挑选出具体执行哪个方法,它通过用各个方法给出的参数类型与特定方法调用所使用的值类型进行匹配来挑选出相应的方法。如果编译器找不到匹配的参数, 就会产生编译时错误,因为根本不存在匹配, 或者没有一个比其他的更好。这个过程被称为重载解析(overloading resolution)。 除了构造方法具有这种重载的情况,普通方法也可以。 5.3 this 关键字 如下代码:  public class Student{    public void setSno(String sno) {        this.sno = sno;   }    public String getSname() {        return sname;   }} 在上面的代码中setSno这个方法有两个参数: 隐式 implict 参数:出现在方法名前的 Student类对象。 在每一个方法中, 关键字 this 表示隐式参数。 显式 explicit 参数:位于方法名后面括号中的参数 sno 在 Java 中, 所有的方法都必须在类的内部定义, 但并不表示它们是内联方法。是否将某个方法设置为内联方法是 Java 虚拟机的任务。即时编译器会监视调用那些简洁、经常被调用、 没有被重载以及可优化的方法。 5.4 java中的初始化代码块 静态初始化块 使用 static定义, 只有当类装载到系统时执行一次,之后不再执行。在静态初始化块中仅能初始化 static修饰的数据成员。 非静态初始化块 非静态初始化块: 在每个对象生成时都会被执行一次, 可以初始化类的实例变量。 代码块执行顺序: 主调类的静态代码块 对象父类的静态代码块 对象的静态代码块 对象父类的非静态代码块 对象父类的构造函数 对象的非静态代码块 对象的构造函数 6. 访问权限控制 6.1 Java 访问权限修饰词 主要分为以下几种情况: ①包访问权限 如果没有指定访问修饰符, 这部分(类、方法或变量)可以被同一个包中的所有方法访问。包访问权限允许将包内所有相关的类组合起来,以使得它们彼此之间可以轻松的相互使用。 对于继承来说,子类是无法访问父类中具有包访问权限的成员 ②public 接口访问权限 标记为 public的部分可以被任意的类使用 ③private 私有访问权限 标记为 private的部分只能被定义它们的类使用。等于说是隔离了自己。 ④protected 继承访问权限 protected也提供包访问权限,也就是说相同包内的其他类可以访问 protected元素,无法跨包访问。 注意:对于继承来说,所有子类都可以访问父类的 protected元素 6.2 基于类的访问权限 修饰词出现在关键字 class 之前,用来控制某个类的访问权限,如:  public class Student {    private String sno;    private String sname;} 这个类中的public就是在告诉大家任何程序员写的java代码都能访问到Student类,没有限制。 注意: 每个 .java 文件(编译单元)只能有一个 public类。这表示每个编译单元都有单一的公共接口。 public类的名称必须与含有该编译单元的文件名一致,包括大小写。 类(内部类除外)的访问权限只能是包访问权限或 public。 如果不希望其他任何人对该类拥有访问权限,可以把所有的构造器都指定为 private,从而阻止任何人创建该类的对象。不过,在该类的 static 成员内部可以创建。 7. static 关键字 7.1静态域 / 静态字段 如果将域定义为 static, 每个类中只有一个这样的域,而每一个对象对于所有的实例域却都有自己的一份拷贝。例如:  class Test{    private static int sno = 1;    private int id;    public static int getSno{        return nextId; // return static field   }   ...} 现在, 每一个 Test对象都有一个自己的 id域, 但这个类的所有实例将共享一个 sno域。换句话说, 如果有 1000 个 Test类的对象, 则有 1000个实例域 id。但是, 只有一 个静态域 sno。即使没有一个 Test对象, 静态域 sno也存在,它属于类,而不属于任何独立的对象。 static初始化只有在第一次创建 Test对象或者调用 Test.sno 的时候才会调用,在那之后,静态域不会重新初始化。初始化的顺序是首先 static,再是其他非 static 对象。 静态域可直接用类名进行调用,例如:  System.out.println(Test.sno); 7.2静态常量 static final 静态变量使用得比较少,但静态常量却使用得比较多。例如在 Math类中定义了一个 静态常量:  public class Math{    public static final double PI = 3.14159265358979323846;   ...} 在程序应用中,可以采用 Math.PI 的形式获得这个常量。无法更改且只初始化一次。 7.3静态方法 静态方法是一种不能向对象实施操作的方法。例如, String 类的 valueOf方法就是一个静态方法。  public final class String implements java.io.Serializable, Comparable , CharSequence { public static String valueOf(Object obj) {        return (obj == null) ? "null" : obj.toString();   }} 在运算时,不使用任何 String对象。换句话说,没有隐式的参数。可以认为静态方法是没有 this 参数的方法。 在下面两种情况下使用静态方法: 方法不需要访问对象状态,其所需参数都是通过显式参数提供(例如:Math.valueOf) 一个方法只需要访问类的静态域(例如:Test.getSno) **8. 对象的清理 在java中当一个对象不再被引用的时候java 的就会任务这个存储垃圾,java会自动调用垃圾回收机制对其进行处理,在一般情况下我们是不需要手动去处理垃圾回收的事情,但也可以手动进行垃圾回收处理,主要有一下两种方式告诉程序需要进行垃圾回收: System.gc(); :告诉垃圾收集器打算进行垃圾收集,而垃圾收集器进不进行收集是不确定的 System.runFinalization(); :强制调用已经失去引用的对象的 finalize方法
经验分享 程序员 微信小程序 职场和发展