Java中的类和方法(方法重载、this关键字)

目录

前言:

什么是面向对象?

什么是类?

类和方法的关系:

方法的定义:

方法重载:

类的定义:

修改类的名字:

实例化: 

利用方法对其属性赋值: 

this关键字: 

this的意义: 

this的使用:

对象的构造以及初始化: 

非构造方法初始化:

构造方法:

this调用构造方法:

构造方法特性:

打印对象: 

总结:


前言:

       Java的特色就是面向对象,对象的上面是什么?对,就是类,这一章,我们就来仔细讲一讲类。

什么是面向对象?

       什么叫面向对象?什么叫面向过程?(如果你只学过C语言,那么说你之前写的代码都是面向过程)其实这两个概念也不用一直去纠结。比如把大象装进冰箱。

 面向对象就会1.打开冰箱2.塞进大象3.关上冰箱。

 而面对过程1.如何打开冰箱?2.如何塞进大象?3.如何关上冰箱?

        面向对象需要:找对象 创建对象 使用对象。

什么是类?

       这其实是一个抽象的概念,类似于C语言中的结构体。我们一般使用的都是基本数据类型(char、double、int之类的),但是定义一本书该怎么办?和C语言一样,需要自定义一种类型,之后一个具体的类叫做对象。

       打个比方,我们老师,同学,亲人等等,这些人。你会发现他们都是人,同属于一个类,这个类就是人。他们都有具体的一些属性:姓名,年龄等等。当这些属性有了具体的数据,比如:张三,18岁。这个张三就是一个具体的类了,可以把他称作为-对象。

       此时你就会理解什么是类了,类和对象的关系是什么。

类和方法的关系:

       我们知道每个人都是人类,都是人这个类的对象,那么人就都有一些共同的做法。比如吃饭,睡觉。

       动物也是类,都有睡觉,大叫的做法。

       我们把一个类的共同做法叫做方法,在类中定义,是一种所属关系。

方法的定义:

       定义方法和定义函数类似。

       有返回值就一定要返回。

       在Java中,方法必须在类里面,方法不能嵌套方法(不能嵌套定义)。在Java中没有方法声明这一说。

       Java方法也会开辟空间(就是方法的栈帧,这里详情请看函数的栈帧-CSDN博客)。

       这里注意:字符串使用length代小括号,数组不用带小括号。

方法重载:

       Java中对方法有一种神奇的用法,会方便我们去调用方法。

       此时我们要求和,分别是対整数和浮点数进行求和,如果都写成方法,就要两种方法,因为类型不同。

public static int addInt(int a, int b){
    return a + b;
}
public static double addDouble(double a, double b){
    return a + b;
}

public static void main(String[] args) {
    int x = 10;
    int y = 20;
    int ret = addInt(x, y);
    System.out.println(ret);

    double d1 = 12.3;
    double d2 = 12.3;
    double sum = addDouble(d1, d2);
    System.out.println(sum);
}

       这种方式比较冗余,都是实现加法,但是要调用两种方法,所以就衍生出:方法重载。

       Java中允许存在相同名称的方法,但是要求返回值、参数列表不同。

       所以此时我们就可以将以上代码修改为:

public static int add(int a, int b){
    return a + b;
}

public static int add(int a, int b, int c){
    return a + b;
}
public static double add(double a, double b){
    return a + b;
}

public static void main(String[] args) {
    System.out.println(add(1, 3));
    System.out.println(add(1.7, 1.5));
    System.out.println(add(1, 2, 3));
}

所以Java中定义: 如果多个方法的名字相同,参数列表不同,则称这几种方法被重载了。

       那么java中到底如何区分呢?有一个东西叫做方法签名,就是经过编译器修改过之后方法最终的名字。

       所以完整方法名:方法路径名 + 参数列表 + 返回值类型。

       我们也可以看具体细节,先编译生成字节码class文件后,在控制台中进入到要查看的.class所在目录,输入:javap -v 字节码文件名字即可。

       我认为看到这里没几人会去实际操作吧,哥哥们。这个只是让你们看到具体的方法名,没必要去实操,但是还是肯定会有的,因为我给的步骤不全,可能有些人就划走了。

       所以我我给出具体步骤(这里我就不给出我写的另一个博客链接了,就这一点不跳转了),打开当前.java文件目录,在当前.java路径中输入cmd,之后先编译,输入javac 文件名.java,之后生成了字节码文件(.class文件)。

(上方是参考图,不是这个文件)之后按照那个输入即可。 

       最后的那个大写的符号就是返回值。

       这个了解即可。

类的定义:

       有了以上基础,我们就来看看类是如何定义的?

class ClassName{
    field; //字段(属性) 或者成员变量
    method; //行为 或者 成员方法
}

       类名注意采用大驼峰定义,成员前写法统一为public(以后会讲解),此处写方法不带static关键字(以后讲解)。

class Person{
    //属性  字段  成员变量 : 定义在类当中 方法外部的变量
    //public 访问修饰限定符
    public String name;
    public int age;

    //静态成员变量
    public static int count = 10;

    //方法   行为
    public void Sleep(){

    }

    //静态成员方法
    public static void staticMethod(){

    }
}

       这里面有两个分类:

       每一个类, 都会产生一个字节码文件(一般最好是这个类前面有public修饰,因为一个文件只能有一个public修饰的类),我们这里为了方便讲解,在一个文件中创建了多个类,一般建议一个文件中一个类。

       此时我们先执行以下代码:

class Person{
    //属性  字段  成员变量 : 定义在类当中 方法外部的变量
    //public 访问修饰限定符
    public String name;
    public int age;

    //静态成员变量
    public static int count = 10;

    //方法   行为
    public void Sleep(){

    }

    //静态成员方法
    public static void staticMethod(){

    }
}

//class ClassName{
//    field; //字段(属性) 或者成员变量
//    method; //行为 或者 成员方法
//}

public class test {
    public static void main(String[] args) {
        int a = 10;//局部变量
    }
}


class PetDog{
    public String name;//名字
    public String color;//颜色

    //狗的属性
    public void barks(){
        System.out.println(name + "汪汪");
    }
}

       之后在文件上右击选取explorer。

       并返回上一级目录点击out,进到最里面会发现生成了好几个class文件。 

       由此可得,一个类就会生成一个.class文件。 不建议一个文件中有多个类,建议一个类放在一个文件当中,这样好管理。
       public修饰的类必须要和文件名相同!而且main方法所在类一般要使用public修饰。

修改类的名字:

       因为我们建议一个文件中一个类,所以不能只通过修改类的名字来进行重命名,不能直接修改,要借助工具。比如我们修改test类的名称。

       但是这只针对一个文件中有一个类,当一个文件中有多个类,这样改就会报错。

匿名对象: 

       和C语言一样,有匿名结构体,也有匿名类和对象。

       匿名对象缺点:只能使用一次,不能重复使用。

public class Again {
    String s;

    public static void main(String[] args) {
        //Again a = new Again();
        //System.out.println(a.s);

        //或者 创建一个匿名类
        System.out.println(new Again().s);
    }
}

实例化: 

       将类进行实例化,其实也就是创建了一个对象,但是这个对象的赋值一开始不能像C语言一样赋值。我们先往下看:

//实例化 -> 就是实例化一个真正的实体
PetDog dog1 = new PetDog();

//通过 new 可以实例化多个对象
PetDog dog2 = new PetDog();
PetDog dog3 = new PetDog();

       所以创建的对象也是引用变量。此时我们对其每一个成员变量进行赋值:

public class test {
    public static void main(String[] args) {
        //实例化 -> 就是实例化一个真正的实体
        PetDog dog1 = new PetDog();
        //赋值
        dog1.name = "lele";
        dog1.color = "black";

        System.out.println(dog1.name);
        dog1.barks();


        int a = 10;//局部变量
    }
}
class PetDog{
    public String name;//名字
    public String color;//颜色

    //狗的属性
    public void barks(){
        System.out.println(name + "汪汪");
    }
}

       使用.来访问对象中的属性和方法。 

       类里面的方法是在方法区存放的,我们以后详解。

利用方法对其属性赋值: 

       我们创建一个方法进行快速赋值:

public class Date {
    public int year;
    public int month;
    public int day;

    public void setDay(int y, int m, int d){
        //相当于一个方法
        year = y;
        month = m;
        day = d;
    }

    public static void main(String[] args) {
        Date date = new Date();
        //date.day = 11; 我们先不进行这样赋值
        date.setDay(1999,1,11);
        Date date1 = new Date();
        date1.setDay(1899,2,3);
    }
}

        注意上面有两个对象创建成功了,都调用了一个方法,方法为了明确到底对谁进行赋值,我们知道是前面使用的对象调用的方法,所以其实有隐藏参数。

this关键字: 

this的意义: 

       所以为了更好的区分,我们在方法中使用属性,前面都加上this.

public void setDay(int y, int m, int d){
    //相当于一个方法
    this.year = y;
    this.month = m;
    this.day = d;
}

       我们先举一个例子:

public class Date {
    public int year;
    public int month;
    public int day;

    public void setDay(int year, int month, int day){
        //相当于一个方法
        year = year;
        month = month;
        day = day;
    }

    public void print(){
        System.out.println("year:" + year + "month:" + month + "day" + day);
    }

    public static void main(String[] args) {
        Date date = new Date();
        //date.day = 11; 我们先不进行这样赋值
        date.setDay(1999,1,11);
        date.print();
        Date date1 = new Date();
        date1.setDay(1899,2,3);
        date1.print();
    }
}

       结果为0是因为: 

       因为局部变量优先,所以要加上this,这样就能更好的区分。

public void setDay(int year, int month, int day){
    //相当于一个方法
    this.year = year;
    this.month = month;
    this.day = day;
}

       this只能引用当前对象,不能引用其他对象。所以我们要习惯使用this。方法里出现属性也要加上this。

public void print(){
    System.out.println("year:" + this.year + " month:" + this.month + " day" + this.day);
}

this的使用:

  • this.成员变量
  • this.成员方法

       this可以后面跟上成员变量,也可以跟上成员方法(就是当前对象调用了方法)。

class PetDog{
    public String name;//名字
    public String color;//颜色

    public void eat(){
        System.out.println(this.name + "吃饭");
    }
    //狗的属性
    public void barks(){
        this.eat();
        System.out.println(name + "汪汪");
    }
}

对象的构造以及初始化: 

非构造方法初始化:

       我们只能针对每一个属性进行初始化。

PetDog dog1 = new PetDog();
dog1.name = "xiaole";
dog1.color = "red";
//构造对象

        我们也可以进行另一种初始化(就地初始化)。

class PetDog{
    //就地初始化
    public String name = "lele";
    public String color = "red";

    public void eat(){
        System.out.println(this.name + "吃饭");
    }
    //狗的属性
    public void barks(){
        this.eat();
        System.out.println(name + "汪汪");
    }
}

public class day_12_27 {
    //静态成员方法
    public static void main(String[] args) {
        PetDog dog1 = new PetDog();
        
    }
}

       一般情况下有特殊业务需求才会使用。 也可以重新赋值,就好像修改变量一样。局部变量使用时一定要进行初始化,但是成员变量(属性)不初始化是默认赋值的。引用类型默认值都是null。

构造方法:

       构造方法:一个非常特殊的方法!没有返回值,方法名必须和类名是一样的,当然也需要使用this。

public Student(){
    //初始化成员变量
    this.name = "daniu";
    this.age = 9;
}

        因为这个构造方法里面没有参数,所以我们称它为无参构造器。

        但是我们之前没有使用过构造方法,是不是意味着构造方法可有可无?我们可以发现,我们没有去调用构造方法,但是它却将对象赋值初始化了,也就是说,构造方法是默认调用的。

       其实,对象产生时(实例化对象时),有两部很关键:为对象分配空间,调用合适的构造方法。 

       当我们没有写任何构造方法时,Java会提供一个默认构造方法。 

public Student(){
    
}

       如何验证,很简单,就是我们没有进行初始化时,默认都是0和null值。 

       所以没有构造方法时,编译器就默认帮你补上构造方法,写了就没有默认构造方法。我们刚才说,合适的构造方法,所以就存在多种构造方法。

class Student{
    public String name;
    public int age;

    //构造方法,接收参数
    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }

    //构造方法
    public Student(){
        //初始化成员变量
        this.name = "daniu";
        this.age = 9;
    }
    
    public void show(){
        System.out.println("姓名:"+this.name+" 年龄:"+this.age);
    }
}

public class day_12_27 {
    public static void main(String[] args) {
        Student s = new Student();
        Student s1 = new Student("zhangsan", 9);
        //直接使用构造方法实例化对象
        s.show();
        s1.show();
    }
}

       所以构造方法之间构成重载关系。 此时我们把无参构造器删除。

       此时发现代码报错,但是编译器不是能自动提供一个无参构造器吗?但是此时有构造器了。如果你没有写构造器,就默认会有无参构造器。但一旦写了一个,无参构造器没就没了。 所以叫做救急不救穷。

       但是有多个成员变量时,我们写构造器就会有些麻烦,难道要把所有参数都写一遍吗?其实IDEA提供了快捷方式(Alt + Insert)或者鼠标右击点击generate,并把全部成员选中即可。

        此时就快捷生成了构造器,生成时我们可以进行选择,生成有参还是无参的构造器。

this调用构造方法:

        this可以调用方法,那么构造方法也可被this调用,比如:

this("鼠标",9);

         这个语法只能出现在构造方法当中!

       不能自己调用自己(this();),且必须出现在当前构造方法的第一行,否则报错。 

       所以有些地方说this代表当前对象是不正确的。 

构造方法特性

       名字必须和类名相同,没没有返回值类型,设置void也不行。创建对象时编译器自动调用,并且在对象的生命周期内只调用一次。构造方法可以重载。我们也可以验证:

class Student{
    public String name;
    public int age;
    public Student() {
        //调用其他构造方法 -> 只能在构造方法中写
        this("鼠标",9);
        System.out.println("gaga");
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("haha");
    }
    public void show(){
        System.out.println("姓名:"+this.name+" 年龄:"+this.age);
    }
}
public class day_12_27 {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.show();
    }
}

        这里一定要注意,不能形成环。

public Date(){
    this(19,1,1);
}

public Date(int y,int m, int d){
    this();
}

打印对象: 

        有没有快捷打印对象每个成员的方法呢?我们如果直接打印就只会打印地址。

public static void main(String[] args) {

    Student s1 = new Student("an",20);
    System.out.println(s1);
}

       我们进入println源码去看,一直点进去可以发现一个熟悉的方法toString。

       也就是说,我们可以在类里面去使用toString方法打印每一个成员。 所以我们还是右击generate生成toString方法(相当于重写toSring方法了)。

public String toString() {
    return "Student{" +
            "name='" + name + '\'' +
            ", id=" + id +
            '}';
}

总结:

       成员属性/成员变量:定义在方法外部,类内部的变量。

  • 21
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值