JAVA学习笔记2

114 阅读16分钟

主要内容:面向对象以及细节(有的地方比难理解和记忆):

1. 面向对象入门:

(1)总结:

先按照名词提取问题领域中的对象。
对对象进行描述,其实就是在明确对象中应该具备的属性和功能。
通过new的方法就可以创建该事物的具体对象。
通过该对象调用它以后的功能.

(2)一般格式:

` //1、创建Car的对象,给对象起个名字
   Car c = new Car();//c是类类型的变量,c指向了一个具体的Car类型的对象
  //2、通过已有的对象调用该对象的功能。格式:对象.对象成员
   c.run();`

(3)对象内存图解

QQ截图20220418133148.png

一个练习:

QQ截图20220418133940.png

(4)成员变量和局部变量(★)

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

区别一:定义的位置不同。 
成员变量定义在类中。
局部变量定义在方法中以及语句里。

区别二:在内存中的位置不同。
成员变量存储在堆内存的对象中。
局部变量存储在栈内存的方法中-

区别三:生命周期不同。
成员变量随着对象的出现而出现,随着对象的消失而消失。
局部变量随着的方法的运行而出现,随着方法的弹枝而消失。

区别四:初始化不同.
成员变量因为在堆内存中,所有默认初始化值-
局部变量没有默认初始化值,必须初始化后才可以使用.

2、封装与构造函数

(1)匿名对象

new Car().run();
匿名对象的使用可以简化书写,但可能会产生垃圾,所以当只调用一次时可以简化成匿名对象书写
PS:调用某个方法也可以用将匿名对象当实参传递 show(new Car())

一个练习:函数参数的传递过程(不同);

QQ截图20220418143442.png

(2)封装

表现: 1、函数就是一个最基本封装体。 2、类其实也是一个封装体。

好处: 1、提高了代码的复用性。 2、隐藏了实现细节,还要对外提供可以访问的方式,便于调用者调用。

(3)private

类中不需要对外提供的内容都私有化,可以设置专门的方法去对私有化的变量进行取值和修改。

面向对象三大特征:封装,继承,多态。

私有仅仅是封装的体现形式而已。

(4)构造函数

需求:为了描述事物更准确,发现事物对应的很多对象一创建时,就有了一些初始化的数据。 对象本身就是构造出来。

构造函数有什么用?可以对对象创速进行初始化。

构造函数怎么在代码中体现呢?

1、没有返回值类型。因为构造对象,创建完就结束,需要结果。void也不要写,因为要有区别与一般函数。
2、构造函数名称和类名—致。
3、没有具体的返回值。

接下来,按照以上三点,在Person类中定义一个构造函数。对象—包建就具备了姓名

   ` Person(String n)
   {
        name = n;
   }`

对象创建时。必须调用对应的构造函数,因为对象需要初始化。 PS:之前写代码的时候其实也调用了,是调用了空参数的构造函数。

构造函数的细节:

1、一个类中可以有多个构造函数,它们的存在是以重载的形式体现的。
2、构造函数中也是有return语句的,用于结束初始化动作的。
3、构造函数是否能被private修饰呢?能,作用:其他程序无法创建该类的对象。

档造函数和——般函数的区别:

1,写法不—样。
2,运行上有差别,对象一创建就会调用对应的构造函数。一般方法是对象创建后,才会调用所需的一般函数。
    问:有了构造函数初始化姓名,那么还需要setName方法吗?
    答:需要,因为对象创建后,如果需要对数据进行修改,可以通过set完成。
3,构造函数在对象创建时,仅调用一次(初始化动作只做一次,而且先执行)。一般方法可以被对象调用多次。

(5)this

构造函数之间不能直接互相调用,故要运用this关键字。

`//初始化姓名
private Person(String n){
    name = n;
}
//初始化姓名和和年龄,既然有初始化姓名的动作,直接调用就可以了,但要用this
Person(String n,int a){
    this(n);//调用一个字符串参数的构造函数
    age = a;
}`

是this记录对象地址,通过this明确被初始化的对象

所以this就代表的对象,哪个对象调用this所在函数,this就代表那个对象。

小细节:调用其他构造函数时,要放在本构造函数的第一行,因为初始化动作要先执行。

this关键字的另一个作用:

可以用this标识哪个变量是成员变量。这个标识可以省略不写。
但是,当局部变量和成员变量同名时,必须用this.来标识成员变量。

3、静态与单例

(1)静态:static

用法:

是一个修饰符,用于修饰成员(成员变量,成员函数).
当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用。类名.静态成员

static特点:

1,随着类的加载而加载。
也就说:静态会随着类的消失而消失。说明它的生命周期最长。
2,优先于的对象存在
明确—点:静态是先存在。对象是后存在的。
3,被所有对象所共享
4,可以直接被类名所调用-

实例变量和类变量的区别:

1,存放位置。
类变量随着类的加载而存在于方法区中-实例变量随着对象的建立而存在于堆内存中-
2,生命周期:
类变量生命周期最长,随着类的消失而消失-实例变量生命周期随着对象的消失而消失。

静态使用注意事项:

1,静态方法只能访问静态成员。非静态方法既可以访问静态也可以访问非静态。
2,静态方法中不可以定义this, super关键字。
因为静态优先于对象存在。所以静态方法中不可以出现this3、主函数是静态的。

静态有利有弊

利处:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。
    可以直接被类名调用。
弊端:生命周期过长。访问出现局限性。(静态虽好,只能访问静态。)

什么使用静态?

要从两方面下手:

因为静态修饰的内容有成员变量和函数.
什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰。对象中的特有数据要定义成非静态存在于堆内存中.

什么时候定义静态函数呢?

当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。

静态的应用

有些共有的功能也能抽取出来,建立一个类。

虽然可以通过建立ArrayTool的对象使用这些工具方法,对数组进行操作。发现了问题:

1,对象是用于封装数据的,可是ArrayTool对象并未封装特有数据。
2,操作数组的每一个方法都没有用到ArrayTool对象中的特有数据。

这时就考虑,让程序更严谨,是不需要对象的

可以将ArrayToo1中的方法都定义成static的。直接通过类名调用即可。

将方法都静态后,可以方便于使用,但是该类还是可以被其他程序建立对象的。为了更为严谨,强制让该类不能建立对象。

可以通过将构造函数私有化完成。

静态代码块

格式:
static{
静态代码块中的执行语句。
}

特点:随着类的加载而执行,只执行一次I用于给类进行初始化的。

PS:静态代码块,构造代码块,构造函数,要清楚

(2)主函数

主函数:是一个特殊的函数。作为程序的入口,可以被jvm调用。

主函数的定义:

public:代表着该函数访问权限是最大的。

static:代表主函数随着类的加载就已经存在了-

void:主函数没有具体的返回值。

main:不是关键字,但是是一个特殊的单词,可以被jvm识别。

(string[] arr):函数的参数,参数类型是一个数组,该数组中的元素是字符串,字符串类型的数组。

主函数是固定格式的: jvm识别。

jvm在调用主函数时,传入的是new String[0]

(3)帮助文档的制作javadoc

(4)初始化过程

Person p =new Person (" zhangsan",20); 该句话都做了什么事情?

1,因为new用到了Person.class.所以会先找到Person.class文件并加载到内存中,
2,执行该类中的static代码块,如果有的话,给Person.class类进行初始化。
3,在堆内存中开辟空间,分配内存地址.
4,在堆内存中建立对象的特有属性。并进行默认初始化。
5,对属性进行显示初始化。
6,对对象进行构喳代码块初始化-
7,对对象进行对应的构造函蛟初始化-
8,将内存地址付给栈内存中的p变量。

(5)单例设计模式

设计模式:解决某一类问题最行之有效的方法。java中有23种设计模式。

单例设计模式:解决一个类在内存只存在一个对象。

想要保证对象唯一:

1,为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象
2,还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。
3,为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。

这三部怎么用代码体现呢?

1、将构造函数私有化
2,在类中创建一个本类对象。
3,提供一个方法可以获取到该对象-

对于事物该怎么描述,还怎么描述- 当需要将该事物的对象保证在内存中唯一时,就将以上的三步加上即可。

饿汉式与懒汉式:

饿汉式:对象被方法调用时才初始化,也叫做对象的延时加载

single类—进内存,就已经创建好了对象-
class single{
    private static single s = new single ( );
    private single(){}
    public static single getInstance ()
    {
        return s;
    }
}

懒汉式:只有调用方法才建立对象

class single{
    private static single s = null;
    private single (){};
    public static single getIhstance()
    {
        if(s==null)
        s=new single();
        return s;
    {
}

4、继承,抽象类,接口

(1)继承

继承概述:

1,提高了代码的复用性-
2,让类与类之间产生了关系。有了这个关系,才有了多态的特性。

注意:千万不要为了获取其他类的功能,简化代码而继承。; 必须是类与类之间有所属关系才可以继承。

Java语言中: java只支持单继承,不支持多继承。

因为多继承容易带来安全隐患:当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪—个.
但是java保留这种机制。并用另—种体现形式来完成表示。多实现。

java支持多层继承,也就是一个继承体系 如何使用一个继承体系中的功能呢?

想要使用体系,先查阅体系父类的描述,因为父类中定义的是该体系中共性功能。通过了解共性功能,就可以知道该体系的基本功能。

那么在具体调用时,要创建最子类的对象,为什么呢?

一是因为有可能父类不能创建对象,
二是创建子类对象可以使用更多的功能,包括基本的也包括特有的。

简单一句话:查阅父类功能,创建子类对象使用功能

子父类中成员特点:

变量:

如果子类中出现非私有的同名成员变量时,子类要访间本类中的变量,用this。

子类要访问父类中的同名变量,用supersuper的使用和this的使用几乎一致。

this代表的是本类对象的引用。
super代表的是父类对象的引用.

函数:

当子类出现和父类一模—样的函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖—样。
这种情况是函数的另一个特性:重写(覆盖)

当子类继承父类,沿袭了父类的功能,到子类中。 但是子类虽具备该功能,但是功能的内容却和父类不一致。 这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容。

覆盖:

1,子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。
2,静态只能覆盖静态.
3、覆盖就是方法要一模一样,和重载不一样,重载时看你参数列表

构造函数:

在对子类对象进行初始化时,父类的构造函数也会运行。 那是因为子类的构造函数默认第一行有一条隐式的语句super(); super() :会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super();

因为父类中的数据子类可以直接获取。所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。所以子类在对象初始化时,要先访间一下父类中的构造函数。 如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。

注意:super一定要定义在子类构造函数的第一行

结论:

子类的所有的构造函数,默认都会访问父类中空参数的构造函数。因为子类每一个构造函数内的第一行都有一句隐式super():

当父类中没有空参数的构造函数时,子类必须手动通过super或者this语句形式来指定要访问的父类中的构造函数。

当然:子类的构造函数第一行也可以手动指定this语句来访间本类中的构造函数。子类中至少会有一个构造函数会访间父类中的构造函数。

final关键字:

可以修饰类,函数,变量
被修饰的类不可以被继承
被修饰的方法不可以被覆写
被修饰的变量只能被赋值一次

(2)抽象类

当多个类中出现相同功能,但是功能主体不同, 这是可以进行向上抽取。这时,只抽取功能定义,而不抽取功能主体。

抽象类的特点:

1,抽象方法一定在抽象类中。
2,抽象方法和抽象类都必须被abstract关键字修饰。
3,抽象类不可以用new创建对象。因为调用抽象方法没意义。
4,抽象类中的抽象方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用。
    如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。

抽象类和—般类没有太大的不同。 该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西。这些不确定的部分,也是该事物的功能,需要明确出现,但是无法定义主体,通过抽象方法来表示。

抽象类比一般类多个了抽象函数。就是在类中可以定义抽象方法。抽象类不可以实例化。

特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。

(3)接口

概述:

初期理解,可以认为是一个特殊的抽象类 当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。 class用于定义类, interface用于定义接口

接口定义时,格式特点:

1,接口中常见定义:常量,抽象方法-
2,接口中的成员都有固定修饰符。
    常量:public static final
    方法:public abstract

接口中的成员都是public的

接口是不可以创建对象的,因为有抽象方法。 需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以实例化。否则子类是一个抽象类。

java不支持多继承,但是通过接口可以多实现

接口的特点:

接口是对外暴露的规则。
接口是程序的功能扩展。
接口可以用来多实现。
类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
接口与接口之间可以有继承关系。

5、多态_Object

简单体现:动物x = new猫();

(1)多态概述

多态的体现

父类的引用指向了自己的子类对象。 父类的弓引用也可以接收自己的子类对象-

多态的前提

必须是类与类之间有关系,要么继承,要么实现-通常还有一个前提:存在覆盖-

多态的好处

多态的出现大大的提高程序的扩展性-

多态的弊端:

提高了扩展性,但是只能使用父类的引用访问父类中的成员。4,多态的应用

(2)类型提升

如果想要调用猫的特有方法时,如何操作? 强制将父类的引用。转成子类类型。向下转型。

Cat c=(cat) a;
c.catchMouse();

千万不要出现这样的操作,就是将父类对象转成子类类型。 我们能转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换。多态自始至终都是子类对象在做着变化。

(3)多态中成员的特点

在编译时期:参阅引用型变量(非静态)所属的类中是否有调用的方法,如果有,编译通过,如果没有编译失败,

在运行时期:参阅对象所属的类中是否有调用的方法。

简单总结就是:成员函效在多态调用时,编译看左边,运行看右边。

在多态中,成员变量的特点:

无论编译和运行,都参考左边(引用型变量所属的类)

在多态中,静态成员函数的特点:

无论编译和运行,都参考左边