初识Java类与对象


了解类与对象

前言

  Java是一门面向对象编程的语言(OOP),注重的是对象。就像我揍你,只关心我和你两个对象,至于具体用拳头还是用棍子,是左勾拳还是右勾拳,这些都不重要。打人,是我这个对象所具有的功能,在创建我的时候就考虑好了。
  这也说明,如果是面向对象,就是找对象,建立对象,发现对象之间的逻辑关系。

面向过程与面向对象的优缺点:
小编在看了zhihu大佬的一篇博客解释的非常通俗易懂,分享给大家
  用面向过程的方法写出来的程序是一份蛋炒饭,而用面向对象写出来的程序是一份盖浇饭。
  蛋炒饭制作的细节不说了,最后的一道工序肯定是把米饭和鸡蛋混在一起炒匀。盖浇饭呢,则是把米饭和盖菜分别做好,你如果要一份红烧肉盖饭呢,就给你浇一份红烧肉;如果要一份青椒土豆盖浇饭,就给浇一份青椒土豆丝。
  蛋炒饭的好处就是入味均匀,吃起来香。如果恰巧你不爱吃鸡蛋,只爱吃青菜的话,那么唯一的办法就是全部倒掉,重新做一份青菜炒饭了。盖浇饭就没这么多麻烦,你只需要把上面的盖菜拨掉,更换一份盖菜就可以了。盖浇饭的缺点是入味不均,可能没有蛋炒饭那么香。
  到底是蛋炒饭好还是盖浇饭好呢?其实这类问题都很难回答,非要比个上下高低的话,就必须设定一个场景,否则只能说是各有所长。如果大家都不是美食家,没那么多讲究,那么从饭馆角度来讲的话,做盖浇饭显然比蛋炒饭更有优势,他可以组合出来任意多的组合,而且不会浪费。
  盖浇饭的好处就是‘’菜”“饭”分离,从而提高了制作盖浇饭的灵活性。饭不满意就换饭,菜不满意换菜。用软件工程的专业术语就是”可维护性“比较好,”饭” 和”菜”的耦合度比较低。蛋炒饭将”蛋”“饭”搅和在一起,想换”蛋”“饭”中任何一种都很困难,耦合度很高,以至于”可维护性”比较差。软件工程追求的目标之一就是可维护性,可维护性主要表现在3个方面:可理解性、可测试性和可修改性。面向对象的好处之一就是显著的改善了软件系统的可维护性。


一. 类:对象的蓝图

可以理解为现实世界中抽象的事物,它包含着一些已知事物和可执行动作。
类是对象的特征提取,是对象的模型,这一点也是在设计类的时候所需要注意的。


二. 对象:类的实例化

  对象的已知事物是实例变量,有不同类型,变量也有很多叫法:字段/属性/成员变量。他们定义在类的内部,方法的外部。忘了说,方法就是可执行动作。
  举一个例子:如果有中国人这个类,它有一些属性:姓名、性别、发色、肤色、等等。这些属性你可以在创建类的时候就定义好,比如黑头发、黄皮肤。姓名每个人不同,有默认值,这个后面会讲。你就可以通过 中国人 这个类来实例化一个个对象:张三、李四、王二啥的。


1. 一起来创建对象

基本方法:

class Chinese {
    public String name;
    public String sex;
    public int age;

    public void life() {
        System.out.println("吃饭、睡觉、打豆豆");
    }
}

public class Learning {
    public static void main(String[] args) {
        Chinese p = new Chinese();
        p.name = "李四";
        p.sex = "man";
        p.age = 10;
        System.out.println(p.name);
        System.out.println("年龄:" + p.age);
        System.out.println(p.sex);
        p.life();
    }
}

结果:
  这里对成员变量都进行了赋值,如果没有初始化,引用类型默认为null,简单类型默认为0值。有两个特殊:char类型默认为’\u000’,boolean类型默认为false。

2. 代码解释

class Chinese 就是创建了一个类,类里面定义了很多属性和life方法
Chinese p = new Chinese() 是实例化,得到p这个对象
对象.属性,是使用的语法,既可以读,也可以写
p.name = "李四"是在写入
System.out.println(p.name)是读取了name并且打印


三. static关键字

1.静态成员变量

 静态成员变量也叫做类变量
  这里介绍一个新朋友,圆点运算符(.)。因为静态成员变量的访问方式是:类名.静态成员变量。你也可以通过new一个对象,从对象.静态成员来访问,但是这是一件合法却不合理的事情。
  因为静态成员变量最大的特点就是不依赖于对象。从内存角度来理解,我们每创建一个类的引用,都会在虚拟机栈上开辟一个栈帧,这个引用指向堆上的一处空间,因为对象是放在堆上的。静态成员变量是存放在方法区的。
来看这个实例:

class Chinese {
    public static int count;
}
 public class Learning {
    public static void main(String[] args) {
        Chinese p = null;
        System.out.println(p.count);
    }
}

  可见这里的p是不指向堆上空间的,却可以打印p.count。不过这样写只限于考题目,一般正规的写法是Chinese.count。也就是通过类名。
静态成员变量只有一份还有这种检验方法:


class Chinese {
    public static int count;
}
 public class Learning {
     public static void main(String[] args) {
         Chinese p1 = new Chinese();
         p1.count++;
         System.out.println(p1.count);
         Chinese p2 = new Chinese();
         p2.count++;
         System.out.println(p2.count);
     }
}

count初始值默认为0,可见p1、p2调用的同一个count,所以毫无疑问,count是不在堆上的。


2. 静态方法

静态方法也叫做类方法 。

class Chinese {
    public static void func() {
        System.out.println("调用静态方法");
    }
}
 public class Learning {
     public static void main(String[] args) {
         Chinese.func();
     }
}

特别注意

  静态方法中不可以使用普通的成员方法。因为普通成员方法,依靠于实例化对象,也就是在new之后,堆上才有他们。而静态方法是不依赖对象,这一点我一直在强调。
静态方法可以使用静态成员变量的,下面上代码:

class Chinese {
    public static void func() {
        count++;
        System.out.println(count);
    }
}
 public class Learning {
     public static void main(String[] args) {
         Chinese.func();
     }
}

静态的只能用自家的,而普通方法却可以使用静态的成员与方法。可以理解为静态的权限比较小。


四. final关键字

  final带来的就是不可更改的效果,要改变final成员变量的任何操作都会报错。final不影响属性存放位置,存放在哪只看有没有static。


五. 重写类中的toString

class Person {
    public String name;
    public int age;
    public String sex;
    
    @Override   //注解:确保重写方法名和被替代的的一样
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}
public class Learning {
    public static void main(String[] args) {
    	Person p = new Person();
        System.out.println(p);
    }
}

如果没有在类中重写toString方法,System.out.println§;会打印p的地址。如果类重新实现toString方法,会自动调用重写过的


六. 封装

1. private

用private来修饰属性或者方法就是封装。private/public是访问修饰符。
  private修饰的属性,只可以在类内部使用。因为如果类的所有成员都能被其他类或者对象访问,会非常的不安全。代码的鲁棒性和可维护性会非常差。
  封装也降低了类的使用者的使用成本,不必关注类当中的过多细节,类的实现者封装好属性与方法就可以。


2. set 和 get 方法

private修饰属性后,类外不可使用。所以用set

class Chinese {
    private String name;
    private String sex;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Chinese{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                '}';
    }
}

 public class Learning {
     public static void main(String[] args) {
         Chinese p = new Chinese();
         p.setName("xiaoming");
         p.setAge(10);
         p.setSex("man");
         System.out.println(p);
         System.out.println(p.getName());
     }
}

来看运行结果:
在这里插入图片描述

类的使用者只要使用set方法,就可以 设置 类属性的值;使用get方法来得到类属性的值。


这里用到了this方法,是为了安全性,后面会讲。
来看一个问题:
  上面的代码不动,只改变setName中内容:

    public void setName(String name) {
        name = name;//原先为 this.name = name;
    }

运行结果如下:
在这里插入图片描述为什么name打印就变成null了呢?
  原因是局部变量优先。name是setName()方法的形参。也就是说,方法中所写是形参自己给自己赋值,并没有作用到类中的属性。
  正是这个原因,我推荐你有使用this的习惯。


七. 构造方法

1. 基本语法

构造方法是一种特殊方法, 使用关键字new实例化新对象时会被自动调用,用于初始化操作。

  一言以蔽之:就是你一new,构造方法就被调用。


语法规则:
  1. 方法名和类名相同
  2. 无返回值
  3. 是每个类都有的。如果你不创建,系统也会默认去创。
  4. 若定义了构造方法,系统默认不执行
  5. 支持重载
来看例子:

class Person{
    Person() {
        System.out.println("调用构造方法Person()!!");
    }
    Person(String name,int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Learning {
     public static void main(String[] args) {
         Person person = new Person();
         Person person1 = new Person("ZTR",21);
         System.out.println(person1);
     }
}

运行结果:


2. this关键字

this代表当前对象的引用!!
  在构造方法中可以使用this,构造方法运行结束,才在堆上开辟空间,创建对象。如果this代表对象,那就说明在this出生之前你就使用它。显然不合理。
  而且由于this代表当前对象的引用,不可以在静态方法中使用。

(1)this();

调用当前构造方法

  来看实例:

class Person{
    String name;
    int age;
    Person() {
        System.out.println("调用构造方法Person()!!");
    }
    Person(String name,int age) {
        this();
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Learning {
     public static void main(String[] args) {
         Person person1 = new Person("ZTR",21);
         System.out.println(person1);
     }
}

运行结果:
我们在调用含有两个参数的构造方法中,使用了没有参数的构造方法。

注意事项

  1. 只可以在构造方法内使用
  2. 必须写在第一行(方法内只可以使用一次)
  3. this();中的参数不可以包含this.data


(2)this.data;

调用当前类的属性

this.name = name;

这就是实例。


(3)this.func();

调用当前类的方法
  直接上代码:

class Chinese {
    public void life() {
        System.out.println("吃饭、睡觉、打豆豆");
    }

    Chinese() {
        this.life();
    }
}
public class Learning {
     public static void main(String[] args) {
         Chinese chinese = new Chinese();
     }
}

运行结果:


八. 代码块

  有普通代码块、实例代码块、静态代码块


1. 普通代码块

  定义在方法中的代码块,没什么卵用,只作了解

2. 实例代码块

  也叫做构造代码块。定义在 类 中的代码块


3. 静态代码块

  由static修饰的,定义在 类 中的代码块


class Tset {
    {
        System.out.println("调用实例代码块");
    }

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

    Tset() {
        System.out.println("调用构造方法");
    }
}

public class Learning {
    public static void main(String[] args) {
        Tset test = new Tset();
    }
}

运行结果
由上图可知,执行顺序为:

  静态代码块    -->    实例代码块    -->    构造方法


注意事项

  静态的代码块只会被执行一次,且最早被执行。
来看实例:

class Tset {
    {
        System.out.println("调用实例代码块");
    }

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

    Tset() {
        System.out.println("调用构造方法");
    }
}

public class Learning {
    public static void main(String[] args) {
        Tset test = new Tset();
        System.out.println("=============");
        Tset test2 = new Tset();
    }
}

运行结果:
在这里插入图片描述可见静态代码块只出现过一次


总结

类可以重复运用在程序中,有很好的拓展性,随时都可以用到。你会发现它的方便,并且爱上它。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值