java类与对象 学习笔记

本文是关于Java中类与对象的学习笔记,详细介绍了面向对象的三大特性:封装性、继承性和多态性,并深入讲解了类与对象的概念,包括对象内存分析、成员属性封装、构造方法、this关键字、static关键字的使用以及代码块的作用。通过对这些概念的理解,有助于深化对Java面向对象编程的掌握。

类与对象

面向对象(Object Oriented)

一、面向对象

三大特性:

  1. 封装性:对象的成员属性和行为看做一个不可分割的整体,一些不想让外界看到的方法也隐藏起来
  2. 继承性:java是类的单继承,接口的多继承,是从一个基础的类上派生出反应一些特殊性的类,如几何类下面可以包括圆类,正方体类等
  3. 多态性:多态是指程序中允许出现重名现象。
    1. 方法重载:根据函数参数的不同,允许同名函数完成不同的工作
    2. 对象多态:子类对象可以和父类对象相互转换,根据其使用的子类不同完成的功能也不同,比如几何类实例对象,new Circle()和new Cube()是不同的,但是都可以用Gemometric定义

二、类与对象

一个类完成定义后,描述的只是一个广泛的概念,其具体操作必须通过对象来完成,格式如下:

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

或者进行分步定义:

  1. 类名称 对象名称 = null
  2. 对象名称 = new 类名称()

然后采取以下方法进行类结构的操作

  1. 对象.成员属性:表示调用类中的成员属性,可以为其赋值或者获取其保存内容
  2. 对象.方法():表示调用;类中的方法
public class ObjectDemo {
    public static void main(String[] args) {
        Person person = new Person("张三", 15);
        System.out.println(person.tell());
    }
}
class Person{
    private String name;
    private int age;
    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }
    public String tell(){
        return "姓名: "+this.name+"、 年龄: "+this.age;
    }
}

1. 对象内存分析

类属于引用数据类型,在使用过程中都要通过关键字new开辟新的内存空间,才能实现成员属性的信息保存

  1. 【heap】堆内存:保存的是对象的具体信息(成员属性),在程序之中内存空间的开辟是通过关键字new进行的
  2. 【stack】栈内存:保存的是一块堆内存的地址,可以通过地址找到内存,然后找到对象内容。

类中的成员属性都是每个对象私有的,而类中的方法是所有对象共有的,方法的信息会存储在“全局方法区”这样的公共内存中

NullPointerException表示的是没有正确实例化对象,也就是有地址,但是地址所指向的内存为空

public class ObjectDemo {
    public static void main(String[] args) {
        Person person1 = new Person("张三", 15);
        Person person2 = person1; // 引用传递,此时person2的地址指向person1的地址,然后指向person1的内存
        System.out.println(person1.tell());
        System.out.println(person2.tell());
    }
}
class Person{
    private String name;
    private int age;
    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }
    public String tell(){
        return "姓名: "+this.name+"、 年龄: "+this.age;
    }
}

当使用引用传递时,要注意栈内存只能保存一个堆内存的信息,当发生指向改变时需要断开原有连接,进行新的连接,此时原有指向的堆内存就没有了入口,成为垃圾,需要GC(Garbage Collection)垃圾回收器不定期的进行回收释放

三、成员属性封装

使用private进行属性的封装,只能够在该类中进行调用,外部无法使用,此时应该提供getter,setter方法来获取和修改private属性。

四、构造方法与匿名对象

构造方法在实例化对象时默认调用new,完成对象属性的初始化操作

  1. 构造方法的名称必须与类名保持一致
  2. 构造方法没有返回值类型声明

实例化类时会默认生成一个无返回值无参数的构造方法,如果类中明确定义了一个构造方法,则不会自动生成无参无返回值的构造方法,也就是一个类中至少存在一个构造方法

构造方法也可进行重载,而且只需考虑参数类型及个数即可

public class ObjectDemo {
    public static void main(String[] args) {
        Person person1 = new Person("张三"); // 使用单参数构造方法,年龄为默认值0
        System.out.println(person1.tell());
    }
}
class Person{
    private String name;
    private int age;
    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }
    public Person(String name){
        this.name = name;
    }
    public String tell(){
        return "姓名: "+this.name+"、 年龄: "+this.age;
    }
}

匿名对象只能在创建的时候使用一次,由于没有入口,以后就无法调用

public class ObjectDemo {
    public static void main(String[] args) {
        System.out.println(new Person("张三", 18).tell())
    }
}

在构造方法为属性初始化的过程中,除了可以传递一些数据的参数之外,也可以接受引用数据类型的内容

public class ObjectDemo {
    public static void main(String[] args) {
        Person person1 = new Person(new Message(), 18);
        System.out.println(person1.tell());
    }
}
class Person{
    private String name;
    private int age;
    public Person(Message msg, int age){ 
        this.name = msg.getInfo();// 接收引用数据的方法
        this.age = age;
    }

    public String tell(){
        return "姓名: "+this.name+"、 年龄: "+this.age;
    }
}
class Message{
    private String content = "李王八";

    public Message(String content){
        this.content = content;
    }
    public Message(){} // 定义了构造方法后,如果想要使用无参构造,必须再定义一下无参构造,否则不能使用
    
    public String getInfo(){
        return this.content;
    }

    public void setInfo(String newConetent){
        this.content = newConetent;
    }
}

五、this关键字

this描述的是本类结构调用的关键字,在Java中this关键字可以描述3中结构的调用

  1. 当前类中的属性:this.属性
  2. 当前类中的方法(普通方法、构造方法):this()、this.方法名()
  3. 描述当前对象

1. this调用本类属性

public class ObjectDemo {
    public static void main(String[] args) {
        Person person = new Person("张三", 15);
        System.out.println(person.tell());
    }
}
class Person{
    private String name;
    private int age;
    public Person(String name, int age){
        this.name = name; // 将接收的参数name赋值给本类的属性name
        this.age = age;
    }
    public String tell(){
        return "姓名: "+this.name+"、 年龄: "+this.age;
    }
}

2. this调用本类方法

public class ObjectDemo {
    public static void main(String[] args) {
        Person person1 = new Person("张老汉", 18);
        person1.tell();
    }
}
class Person{
    private String name;
    private int age;
    public Person(){ // 应当保留一个没有this()的构造方法,作为程序的出口
        System.out.println("创建了一个构造方法");
    }
    public Person(String name){
        this(); // this()必须放在构造方法的第一行,因为调用别的属性的时候,构造方法必须第一个被调用
        this.name = name;
    }
    public Person(String name, int age){
        this(name);
        this.age = age;
    }

    public void tell(){ // 普通方法不能使用this()调用构造方法
        System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
    }
}

主要用途是面对多参构造,比如四个参数的构造方法,可以通过this依次调用,省去写多个赋值语句的问题

3. this表示当前对象

public class MyThreadDemo{
    public static void main(String[] args) throws Exception{
        new Message().printThis();
        new Message().printThis();
    }
}
class Message{
    public void printThis(){
        System.out.println("【message类】this = "+this );
    }
}
输出:
【message类】this = Message@133314b
【message类】this = Message@b1bc7ed

可以看出this表示了不同的对象

六、static关键字

普通成员(非static)和静态成员(static)

1. static属性

如果想要类中的某个属性定义为公共属性(所有的对象都可以使用的属性),则可以加上static关键字

public class ObjectDemo {
    public static void main(String[] args) {
        Person person1 = new Person("张老汉", 18);
        person1.tell();
    }
}
class Person{
    static String country = "China";
    private String name;
    private int age;
    public Person(){
        System.out.println("创建了一个构造方法");
    }
    public Person(String name){
        this();
        this.name = name;
    }
    public Person(String name, int age){
        this(name);
        this.age = age;
    }

    public void tell(){
        System.out.println("姓名: "+this.name+"、 年龄: "+this.age+"、 国籍: "+ this.country);
    }
}

static表示的公共属性,如果不使用static,则会为每个属性都创建一个country的对象,造成性能下降和内存浪费。

  1. static的属性内容不在堆内存中保存,而是存储在公共数据区
  2. 使用static的属性表示的是类属性,而不是某个对象的属性,类属性可以直接用类名调用(不提倡使用对象名调用类属性)
  3. 类属性static虽然定义在类中,但是可以在没有实例化对象的时候直接调用该属性,因为普通属性保存在堆内存中,需要有栈内存进行引用,而static属性保存在全局数据区

2. static方法

如果static定义了方法,则此方法可以在没有实例化对象的时候调用

public class ObjectDemo {
    public static void main(String[] args) {
        Person person1 = new Person("孙笑川", 88);
        person1.tell();
        Person.setCountry("日本平津");// 使用类名调用静态方法
        Person.getCountry();

    }
}
class Person{
    static String country = "China";
    private String name;
    private int age;
    public Person(){
        System.out.println("创建了一个构造方法");
    }
    public Person(String name){
        this();
        this.name = name;
    }
    public Person(String name, int age){
        this(name);
        this.age = age;
    }
    public static void setCountry(String c){ // 静态方法修改静态属性
        country = c;
    }
    public static void getCountry(){
        System.out.println("国籍: " + Person.country); // 静态属性使用类名调用
    }
    public void tell(){
        System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
    }
}
输出:
创建了一个构造方法
姓名: 孙笑川、 年龄: 88
国籍: 日本平津

一些注意事项:

  1. static方法不能调用非static的方法,因为类操作不能变成对象操作
  2. 但是对象的方法可以使用类方法,非static方法可以是调用static方法或属性
  3. 使用static的方法或属性,可以在没有实例化的时候调用,如果没有了实例化对象,也就没有了this关键字,所以static方法中无法使用this关键字的原因就在于此
  4. 非static方法的调用,必须通过实例化对象才能调用
public class ObjectDemo {
    public static void main(String[] args) {
        new Person("孙笑川", 88);
        new Person("哮喘天皇", 24);
        System.out.println(Person.getCount());
    }
}
class Person{
    private static int count = 0; // 类共同属性,不受实例化对象影响
    private String name;
    private int age;
    public Person(String name, int age){ // 调用构造方法,会修改static属性count+=1
        this.name = name;
        this.age = age;
        count += 1;
    }
    public static int getCount(){
        return count;
    }
}

七、代码块

代码块使用‘{}’定义起来的一段程序,根据声明位置不同和声明关键字不同,可以分为:普通代码块,构造代码块,静态代码块和同步代码块

1. 普通代码块

普通代码块是定义在方法中的代码块,可以解决代码块在一个方法中过长,导致出现变量重复定义的问题,例如

public class ObjectDemo {
    public static void main(String[] args) {
        if (true){
            int x = 10;
            System.out.println(x);
        }
        int x = 100;
        System.out.println(x);
    }
}
输出:
10
100

变量名就不会出现重复的问题,代码块相当于一个隔断

2. 构造代码块

将代码定义在一个类中,这样就成为了构造代码块,可以在使用关键字new实例化新对象的时候进行调用,例如

public class ObjectDemo {
    public static void main(String[] args) {
        new Person("孙笑川",22).tell();
    }
}
class Person{
    private static int count = 0;
    private String name;
    private int age;
    public Person(String name, int age){
        this.name = name;
        this.age = age;
        count += 1;
    }
    {// 定义在类中的构造代码块,优先于构造方法调用
        System.out.println("调用了构造代码块");
    }
    public static int getCount(){
        return count;
    }

    public void tell(){
        System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
    }
}

3. 静态代码块

使用static定义的代码块

public class ObjectDemo {
    public static void main(String[] args) {
        new Person("孙笑川",22).tell();
        new Person("莱莱",80).tell();
    }
}
class Person{
    private static int count = 0;
    private String name;
    private int age;
    public Person(String name, int age){
        this.name = name;
        this.age = age;
        count += 1;
    }
    static {// 静态代码块无论进行多少次实例化对象,只在第一次实例化时调用,且优先于构造方法调用
        System.out.println("调用了构造代码块");
    }
    public static int getCount(){
        return count;
    }

    public void tell(){
        System.out.println("姓名: "+this.name+"、 年龄: "+this.age);
    }
}

总结

  1. 面向对象的三大特性,继承性,封装性,多态性
  2. 对象是类的实例,类只能通过对象来使用
  3. 类的组成:成员属性(Field)、方法(Method)
  4. 如果一个对象没有被实例化而直接使用,就会出现空指向异常
  5. 类属于引用数据类型,传递的是堆内存的地址
  6. 类通过private进行封装,封装的属性不能被外部调用,只要是属性都要被封装
  7. JVM自动生成一个无参构造方法,如果自己设置了有参构造,则想要使用无参构造,必须重新定义一个无参构造
  8. this表示当前对象,this()调用本类的构造方法,但必须放在首行,且只能放在构造方法中
  9. static属性是公共的,static方法是类共有的
public class Book {
    public static void main(String[] args) {
        new BookClass("asodi",124.23).getInfo();
        new BookClass("a12s", 12.42).getInfo();
        new BookClass("xsdfa",2.42).getInfo();
    }
}
class BookClass{
    private static long bookNumber = 1000;
    private static int count = 0;
    private String name;
    private double price;

    public BookClass(String name, double price){
        this.name =name;
        this.price=price;
        count++;
    }

    public double getPrice(){
        return this.price;
    }
    public static long getBookNumber(){
        return bookNumber+count;
    }
    public String getName(){
        return this.name;
    }
    public static int getCount(){
        return count;
    }
    public void getInfo(){
        System.out.println("book name is "+this.name+"、price is "+"、the number is "+ BookClass.getBookNumber());
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值