类和对象---JAVA内功心法

类和对象的定义:

类:

在我们Java中具有许多基本数据类型,比如int、char、boolean等等,但如果我们需要描述一个活生生的人,这些基本数据类型显然满足不了我们的需求。

因此,java提供了一个很好的解决方法,就是将一个现实生活中的对象抽象成一个类。类是对一个实物(对象)进行描述的,主要描述这个实物(对象)具有哪些属性。比如说一个学生,如果我们要粗略的了解他,那就需要学号(int id)、姓名(String name)、年龄(int age)、行为(void action)等等。而我们的类就是用来描述像学生这一些对象的。

对象:

面向过程:

面向过程编程就是针对项目逻辑进行编程,强调一步一步进行。结果就是代码之间的耦合度过高,牵一发而动全身。

面向对象:

面向对象则是把面向过程的代码进行抽象,是模块化编程。好处就是模块之间相互独立,可以在原有的代码之上进行继承操作,更加方便,利于使用。

如果说类是一张设计图纸,那么对象就是根据设计图纸创造出来的一个具体的实物。比如说印在纸上的印子(对象)是通过印章(类)印出来的,它两的关系就是类和对象的关系。

例1:定义一个学生类:

public class Student {
    public int id;
    public String name;
    public int age;
    public void action() {
        System.out.println(name + "去学习");
    };
}

例2:创建一个学生类的对象:

public class test {
    public static void main(String[] args) {
        //类名 对象名 = new 类名();
        Student s = new Student();
        //同一个类可以创建多个实例
        Student s2 = new Student();
    }
}

创建完之后你就可以通过对象来做一些事情

public class test {
    public static void main(String[] args) {
        //类名 对象名 = new 类名();
        Student s = new Student();
        s.name = "张三";//给这个学生命名
        s.action();//执行学生的行为
    }
}

新建对象时的一些注意事项:

public class test {
    public static void main(String[] args) {
        //注意事项
        //1.
        Student student1 = new Student();
        Student student2 = new Student();
        student1 = student2;//不能这样指向!这样表示student1的引用指向了student2引用的指向
        //2.
        Student student3 = new Student();
        student3 = new Student();
        student3 = new Student();
        student3 = new Student();
        //这样子也只会指向一个对象
    }
}

this指针:

定义:

this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。

this指针只能引用当前对象,不能引用其他对象。

public class Student {
    public int id;
    public String name;
    public int age;
    public void setData (int id, String name, int age) {
        id = id;
        name = name;
        age = age;
    }
}

在以上这种情况下,我们该如何知道id、name、age哪个对应着哪个呢?是成员对象里的还是传参的参数呢?

public class Student {
    public int id;
    public String name;
    public int age;
    public void setData (int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}

那么在这时我们加上this指针就可以清楚的了解到前面的变量是属于当前对象的,后面的变量是属于传过来的参数的。

this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this负责来接收。

public class Student {
    public int id;
    public String name;
    public int age;
    public void setData (Student this, int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
}

构造方法:

构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。

在Java中如果你没有重写构造方法,那么Java会自动给你提供一个构造方法。形如

如果你自己写了一个构造方法,那么编译器是不会再给你提供构造方法的。

构造方法是可以重载的。

有参构造:

无参构造:

我们还可以用this()来进行简化:

this()函数必须放在第一行!!

不过this()不能有环

初始化:

有参构造的初始化:

    public static void main(String[] args) {
        Student student = new Student(2, "李四", 20);
        System.out.println(student.id + " "  + student.name + " " + student.age);
    }

无参构造的初始化:

    public static void main(String[] args) {
        Student student = new Student();
        System.out.println(student.id + " "  + student.name + " " + student.age);
    }

就地初始化:

public class Student {
    public int id = 1;
    public String name = "张三";
    public int age = 19;
    public Student(int id, String name, int age) {
    }

    public Student() {
    }
}

局部变量在使用时必须要先初始化,而成员变量在使用时可以不初始化,因为Java在创建一个成员变量时会做以下事情:

  1. 先查看一下该类有没有被加载过。

  1. 给创建的对象分配空间。

  1. 处理并发安全问题(比如多个线程申请对象,JVM要保证给所有对象分配空间)。

  1. 初始化所分配的空间(给对象的成员对象赋予默认值)。

  1. 设置对象头信息。

  1. 调用构造方法。

封装:

面向对象有三大基础特性:封装、继承、多态

封装的定义:

封装就是将数据和对数据的一些操作进行有机融合隐藏对象的属性和实现细节,仅公开一些对外的接口来和对象进行交互。

就像电脑一样,在电脑中,实际工作的是CPU、GPU、硬盘等硬件,然而我们在使用电脑时都是用鼠标、键盘、usb接口来对电脑进行操作。

封装提高了代码的复用性,便于调用者的使用,提高了安全性。

包:

包的定义:

包就是将多个不同的类、接口组合在一起进行组织管理的集合。(类似一个文件夹)

在一个工程中允许存在相同名称的类,只要处在不同的包中即可。

包的导入:

我们可以用import语句来导入包:

import java.util.Scanner;
//需要java.util里的其他类可以这样写:
//import java.util.*;

//不过我们更建议第一行的方法,因为不容易出现歧义
//比如java.util.*和java.sql.*里都含有Date类,此时就会报错

//我们还可以导入包中的静态方法或者静态类
import static java.lang.Math.*;
//此时在使用的时候会更加方便
double x = 30;
double y = 40;
// 静态导入的方式写起来更方便一些.
// double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
double result = sqrt(pow(x, 2) + pow(y, 2));

也可以在创建对象或者调用方法的时候导入包

        //创建对象时
        java.util.Scanner sc = new java.util.Scanner(System.in);

        //使用方法时
        int[] arr = {1,2,3,4,5};
        System.out.println(java.util.Arrays.toString(arr));

自定义包:

我们在src中new一个包出来。

一般企业的命名规则是他们的域名倒过来命名的,比如我的域名是demo1.feng.com

那么我命名的时候就可以com.feng.demo1

D:\****\src\com\demo1\feng创建完成我们就得到这样的文件地址

然后我们就可以在包中写我们的类或接口啦。

访问限定符:

访问限定符规定了类或字段的 被访问权限(在类外可以被使用/在类外不可以被使用)。

常用的限定符有以下几种:

static:

定义:

虽然说static是静态的意思,但是它实际上与它的字面意思关系不大。

在类中,被static修饰的成员变量称为类变量,它与类的生命周期一致,在内存中只加载一次,因此只存在一份,它不属于某个对象,是所有对象都可以修改、访问的。

static的作用:

方便我们直接使用类来访问变量或调用方法,不用创建对象。只要类被加载了,就可以通过类名来调用。static可以用来修饰成员方法、成员变量,还可以在类中编写static代码块来优化程序性能。

静态成员变量的特性:

  1. 不属于某个具体的对象,是类的属性,是所有对象共享的,不存储在某个对象的空间中。

  1. 既可以通过对象访问,也可以通过类名访问,不过更加推荐用类名访问。

  1. 类变量存储在方法区中。

  1. 随着类的加载而创建,随着类的卸载而销毁, 生命周期伴随着类的一生

class Student {
    private String name;
    private int age;
    public static String classroom = "306";//static修饰的成员变量
    //private static String classroom = "306";//private修饰的成员变量
    //不能在类外被直接调用!!
}

public class Demo1 {
    public static void main(String[] args) {
        System.out.println(Student.classroom);//可以用类名直接调用
        
        Student student = new Student();
        System.out.println(student.classroom);//也可以用对象直接调用
        //不过不推荐这种写法,多此一举!
    }
}

静态成员的初始化:

  1. 就地初始化

  1. 静态代码块初始化

  1. 静态方法初始化

    private static String classroom = "306";//就地初始化

    //classroom = "308";编译错误,实例代码块不能初始化静态成员变量

    static {//静态代码块初始化
        classroom = "308";
    }

    public static void setClassroom(String name) {//静态方法初始化
        classroom = name;
    }

静态成员初始化会在类加载的时候进行初始化,也就是程序启动的时候进行初始化。

首次创建类对象、访问类的静态成员(变量或方法)会引发类加载。

顺序优先级:静态成员变量 = 静态代码块 > 非静态成员变量 = 非静态代码块 > 构造函数

静态方法的特性:

  1. 静态方法也叫类方法而对象方法也称为实例方法或非静态方法。

  1. 静态方法不属于某个具体的对象,是类的属性,是所有对象共享的,不存储在某个对象的空间中。

  1. 既可以通过对象访问,也可以通过类名访问,不过更加推荐用类名访问。

如果我们的静态成员变量被private与static 修饰,

且我们在类外需要获取这个静态成员变量,那我们可以借助静态方法来实现:

class Student {
    private String name;
    private int age;
    private static String classroom = "306";//private、static修饰的成员变量

    public static String getClassroom() {//静态方法
        return classroom;
    }
}

public class Demo1 {
    public static void main(String[] args) {
        System.out.println(Student.getClassroom());//可以用类名直接调用

        Student student = new Student();
        System.out.println(student.getClassroom());//也可以用对象直接调用
        //不过不推荐这种写法,多此一举!
    }
}

3.在静态方法中不能调用非静态的成员变量。

4.静态方法中不能调用非静态方法

5.静态方法不能重写,无法用来实现多态(下一篇咱们细说)

代码块:

1.普通代码块:

    public void goToClassroom() {
        System.out.println("去上课");
    }//普通代码块:定义在方法里的代码块

2.构造代码块(实例代码块):

构造代码块只有在创建对象的时候才会执行每创建一个对象,执行一次

class Student {
    private String name;
    private int age;

    {
        name = "张三";
        age = 15;
        //classroom = "308";编译错误,实例代码块不能初始化静态成员变量!!
    }//构造代码块:一般用来初始化实例成员变量

}

3.静态代码块:

静态代码块无论创建多少个对象只会执行一次

class Student {
    private String name;
    private static String classroom = "306";//就地初始化

    static {
        classroom = "308";
        getClassroom();
        //name = "张三";     编译错误:静态代码块不可初始化实例成员变量!!
    }//静态代码块:一般用于初始化静态成员变量,也可以调用静态方法。

    public static String getClassroom() {//静态方法
        return classroom;
    }
}

代码块的执行顺序:

优先静态代码块执行(只执行一次!!),然后到实例化代码块,最后构造函数执行。

class Student {
    private String name;
    private int age;
    private static String classroom;

    static {
        System.out.println("静态代码块执行");
    }

    {
        System.out.println("实例代码块执行");
    }

    public Student() {
        System.out.println("构造函数执行");
    }
}

public class Test {
    public static void main(String[] args) {
        Student student1 = new Student();
        System.out.println();
        Student student2 = new Student();
    }
}

内部类

内部类就是将一个类定义在另一个类或者方法的内部

1.实例内部类

class A {
    private int a;
    private int b;
    private int c;
    a = 100;//编译错误,不能再变量定义阶段修改变量值!!!
    public class B {//这个B类称为实例内部类
        int c;
        void change() {
            a = 100;
            b = 200;//可以在内部类访问外部类的成员变量
            c = 300;//如果有同名,优先访问自己的(内部类)的成员变量
            this.c = 400;//如果要访问外部类的同名成员变量,要加this
        }

        public B() {
            System.out.println("内部类B的构造函数");
        }
    }

    public A() {
        System.out.println("外部类A的构造函数");
    }
}

public class Demo2 {
    public static void main(String[] args) {
        A.B ab = new A().new B();//实例化内部类
    }
}

构造顺序:先A后B

2.静态内部类

class A {
    private int a;
    static int b;
    private static int c;

    static void outmethod1() {
        
    }

    void outmethod2() {

    }
    
    static class C {//这个C类称为静态内部类
        void method() {
            //outmethod2();编译错误,静态代码块只能访问静态方法
            //a = 100;编译错误,静态代码块只能访问静态成员变量

            b = 200;
            c = 200;//静态代码块能够访问静态成员变量
            outmethod1();//静态代码块能够访问静态成员方法
        }
    }
}

public class Demo2 {
    public static void main(String[] args) {
        A.C ab = new A.C();//创建静态内部类的时候不用先创建外部类
    }
}

3.局部内部类

class A {
    void method() {
        class D {//这个D类称为局部内部类
            //局部内部类不能被public、static等访问限定符修饰
            //局部内部类只能再方法体内部调用
        }
    }

}

对象的打印:

如果不重写toString方法

class Person {
    private String name = "张三";
    private int age = 30;
}


public class Demo3 {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person);
    }
}

打印的是类名+地址

重写toString方法之后就可以打印我们想要看到的信息啦:

class Person {
    private String name = "张三";
    private int age = 30;

    @Override
    public String toString() {//重写toString方法
        return "[" + this.name + ", " + this.age + "]";
    }
}


public class Demo3 {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person);
    }
}

写这种内功心法的博客总是耗费我很多时间,不过基础十分重要!时间花的是值得的,大家要多多加油巩固基础哦。

每个人都是生活里的主角!_哔哩哔哩_bilibili

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值