java学习基础课之面向对象(渡一教育)【构造方法;程序块;this】(四)

前提:
之前学习类的内部成员Person
1.属性—静态描述类的特征(变量 存值) name
2.方法—动态描述类的行为(做事情) eat
现在补充两个成员
3.构造方法—用来创建当前类的对象(方法 很特殊)
4.程序块(代码块)—理解为就是一个方法(非常特殊的 无修饰符无参数无返回值无名字)

现在说:类中的第三个成员:
构造方法—做事情

一、构造方法

  1. 作用: 只有一个作用,就是构建(构造)当前类的对象
  2. 写法:
权限修饰符  与类名一致的方法名 (参数列表) [抛出异常可有可无]{
			一件事情  创建一个对象(当前类Person)
			返回对象;
		 }
  1. 用法: 通过new关键字调用

假设有一个类Person,那么构造函数如何使用?看下面的代码:
Person p = new Person
这不是和以前定义一个对象一样吗?对就是一样的,其实以前我们虽然没有定义构造函数,也能定义对象,是因为如果不自己定义一个构造函数的话,编译器会自动默认为我们定义了一个构造函数。

  1. 特点:
  • 每一个类都有构造方法,若自己在类中没有定义,系统会默认提供一个无参数的构造方法
  • 若在类中自己定义了构造方法,则默认无参数的构造方法即被覆盖

    假设自己定义了下面的构造函数,那么原来的默认无参数的构造函数会被覆盖。

 public Person(){
        System.out.println("我是无参数的默认的构造方法");
    }
  • 构造方法是否存在方法重载?----存在构造方法重载

通常情况下,我们自己可能自己设计了一个构造函数,要求你在定义对象的时候,必须输入参数,比如下面这个自己设计的构造函数:

public Person(String s,int i,String n){
        this();
        System.out.println("我是带参数的构造方法");
        //创建了一个对象(开辟空间)
        name = s;//如果属性与变量重名?
        age = i;
        sex = n;
        //返回了创建的这个对象空间的引用
    }

这个时候,原来的默认无参数的构造函数就会被覆盖了,那么当另一个人想要使用我们自己设计的构造函数定义一个对象的时候,就会出现一个问题,那就是,别人并不知道你到底要求我们输入哪几个参数才可以定义一个对象。所以一般情况下,我们会自己再重载一个没有参数的构造函数,方便其他开发人员使用,其他人员可以自己通过p.name的方式进行对象属性的定义。

public Person(){ }  //重载一个无参数的构造函数
  1. 每一个类都有构造方法
    若不定义,系统会默认提供构造方法
    为什么要定义构造方法? 什么时候需要设计构造方法?
    在创建对象的同时,想要一并做一些事情,默认提供的构造方法是不会做的,这个时候我们可以自己定义构造方法(无参数的构造方法内做事 也可以定义带参数的)。

那么就会思考一个问题?为什么使用构造函数?
如果没有构造函数:我们定义给对象赋予属性的时候,往往是:
Person p = new Person
p.name="郑中拓"
p.age=18
这样往往很麻烦。
但是如果有了构造函数:我们可以在构造函数里面写上:

public Person(String s,int i,String n){
        this();
        System.out.println("我是带参数的构造方法");
        //创建了一个对象(开辟空间)
        name = s;
        age = i;
        sex = n;
        //返回了创建的这个对象空间的引用
    }

这样在定义对象的时候,就会默认有了这些属性。
还有另外一个问题,名字应当见名知意,当你定义对象的时候,要求你必须输入参数,但是也会提醒你,但是提醒你的是,输入s,i,n,看到这些参数名字无法见名知意,所以考虑将s改为name ,i改为age ,n改为sex。如下:

public Person(String name,int age,String sex){
        System.out.println("我是带参数的构造方法");
        //创建了一个对象(开辟空间)
        name = name;//如果属性与变量重名?
        age = age;
        sex = sex;
        //返回了创建的这个对象空间的引用
    }

但是这样就会和类的属性弄混。由于就近原则,name = name;第一个name本来表示属性name,但是就近会认为是变量name,出现问题。所以出现了this。代码如下:解析见第三节。

public Person(String name,int age,String sex){
        //创建了一个对象(开辟空间)
        this.name = name;//如果属性与变量重名?
        this.age = age; //属性的话最好以后都写this
        this.sex = sex;
        //返回了创建的这个对象空间的引用
    }

二、程序块(代码块)

类的第四个成员—程序块(代码块)

  1. 作用:
    跟普通方法一样 做事情的
  2. 写法:
    可以认为程序块是一个 没有修饰符 没有参数 没有返回值 没有名字的特殊方法
{
		}

例子:

    {
        System.out.println("我也是一个块 哈哈");
    }
    {
        System.out.println("我是一个普通的程序块");
    }
    {
        System.out.println("我又是一个块");
    }
  1. 用法:
  • 块也需要调用才能执行,我们自己调用不到(没有名字)
  • 每一次我们调用构造方法之前,系统会帮我们自动的调用一次程序块,让他执行一遍。
  1. 特点:
    没有什么重载的概念(压根连名字都没有 连参数都没有)
    ,但是可以在类中定义,多个程序块
  2. 块可以在里面写一些程序,我想要在创建对象之前执行。

三、this关键字

构造方法中,属性与变量重名,必须需要一个代替词,代替对象

this关键字的使用

  1. 是一个关键字(指代词) ,代替的是某一个对象 (当前调用属性或方法时的那个对象)
  2. this既然代替的是一个对象
  • this可以调用什么? 属性 方法 可以

  • this可以调用构造方法么? 可以 在一个构造方法内可以调用另一个构造方法

    构造方法 和一般方法:有顺序 认为构造方法早于一般方法
    在一般方法内调用构造方法呢? 不行
    构造方法可以重载,构造方法可以调用另一个构造方法吗?可以

    通过this(); 省略了构造方法的名字(必须与类名一致)
    必须在另一个构造方法内调用 必须在程序的第一行

  • 方法之间来回的调用???
    写法可以的(编译好用) 执行可能会产生StackOverflowError 栈溢出错误,分析见下面的代码。
    构造方法不能来回互相调用(编译就不好用)

public class Person {

    public String name;
    public int age;
    public String sex;

    public Person(){
        System.out.println("我是人类的构造方法");
    }
    public Person(int a){
        System.out.println("我是人类带int参数的构造方法");
    }


    public void eat(){
        this.sleep();  //和下面的来回调用
        System.out.println("这是人类的吃饭方法");
    }
    public void sleep(){
        this.eat();//和上面的来回调用
        System.out.println("这是人类的睡觉方法");
    }
    public static void main(String[] args){
        Person p = new Person();
        p.eat();
    }
}//栈溢出

在这里插入图片描述
3. this调用的过程可以放置在哪个位置写?
调用属性或方法,这一行代码,可以放置在类中的任何成员位置,上下顺序随意。

Scanner补充

关于Scanner类及其中方法的使用
1.导包 java.util
2.创建对象 Scanner input = new Scanner(System.in);
3.做事情 int value = input.nextInt();
String value = input.nextLine();

import java.util.Scanner;
public class TestScanner {
    public static void main(String[] args){
        //利用数组实现用户的登录
        //1.有小数组来充当数据库
        //2.利用Scanner让用户输入
        Scanner input = new Scanner(System.in);
        System.out.println("请输入账号:");
        String name = input.nextLine();//阻塞效果 
        //input这个小人在计算机中的消息队列内等着读取
        System.out.println("请输入密码");
        int password = input.nextInt();//阻塞效果
 		System.out.println("接收到了账号:"+name);
        System.out.println("接收到了密码:"+value);
    }
}
//可以正常运行
/*
请输入账号:
郑中拓  然后回车
请输入密码:
123回车
然后出现:
接收到了账号:郑中拓
接收到了密码:123
*/

但是如果换成下面的代码,就不可正常运行了。

import java.util.Scanner;
public class TestScanner {
    public static void main(String[] args){
        //利用数组实现用户的登录
        //1.有小数组来充当数据库
        //2.利用Scanner让用户输入
        Scanner input = new Scanner(System.in);  
        //input这个小人在计算机中的消息队列内等着读取
        System.out.println("请输入密码");
        int password = input.nextInt();//阻塞效果
        System.out.println("请输入账号:");
        String name = input.nextLine();//没起到阻塞的作用,证明它读取到东西了
 		System.out.println("接收到了账号:"+name);
        System.out.println("接收到了密码:"+value);
    }
}
//不可以正常运行
//输出:请输入密码:1234然后enter之后,直接将所有结果输出
//为:接收到了账号   接收到了密码:1234

问题在于哪??解析:
在这里插入图片描述

我们输入的东西,实际上存储在一个消息队列中。
第一次输入的时候:消息队列中:郑 中 拓 回车\n
我们实际输入四个字符,nextLine方法会以回车符作为截止,然后将所有字符(四个包括回车符)读出来,然后扔掉回车符,将前面所有的字符组为字符串作为返回值。
此时消息队列中没有内容了,input小人又开始新的工作。
输入:1 2 3 \n
nextInt方法会读取回车符之前的字符读取出来,回车符留在队列中。然后读取到的123实际是为字符串“123”然后转换为int类型作为返回值,如果发现不是数字,会报错。
但是此时消息队列中还存在回车符。但h是整个执行过程没有问题。

但是第二段错误的代码:
消息队列中先读入1 2 3 \n nextInt方法将123作为返回值,消息队列中还剩下一个回车符。
input这个小人如果没有读取到东西就等待输入,但是如果读到东西,就不等了。然后input这个小人读取到了回车符,所以没有等,直接给nextLine方法传过去了,因为nextLine方法就是读到回车符就截止了。

修改:

import java.util.Scanner;
public class TestScanner {
    public static void main(String[] args){
        //利用数组实现用户的登录
        //1.有小数组来充当数据库
        //2.利用Scanner让用户输入
        Scanner input = new Scanner(System.in);
        //input这个小人在计算机中的消息队列内等着读取
        System.out.println("请输入密码");
        String password = input.nextLine();//阻塞效果
        //1.利用nextLine方法读取一个空回车符
        //input.nextLine();// ""
        //2.利用next方法读取字符串  next方法读取方式与nextInt一样 不读取回车符
        //3.将账号和密码都统一的用nextLine来读取
        //  String---->int
        //  int--->String   5+""  加一个空号就直接变成字符串了
        //  数据类型转化的问题   前提 同种大数据类型一致 基本-基本  引用-引用
        //  基本<--包装类-->引用 int--Integer  char--Character  byte--Byte  float--Float
        int value = Integer.parseInt(password);//NumberFormatException
        System.out.println("请输入账号:");
        String name = input.nextLine();//阻塞效果 如果没有阻塞证明读取到东西了
        System.out.println("接收到了账号:"+name);
        System.out.println("接收到了密码:"+value);
        System.out.println("105"+5+5);//10555
    }
}//这样就可以正常运行了。

任务:

  1. 计算器
import java.util.Scanner;

public class Calculator {

    //设计一个方法  加法运算   是否需要提供条件  两个元素  是否需要结果  计算结果
    public float add(float a,float b){
        return a+b;
    }
    //设计一个方法  减法运算
    public float substact(float a,float b){
        return a-b;
    }
    //设计一个方法  乘法运算
    public float multiply(float a,float b){
        return a*b;
    }
    //设计一个方法  除法运算
    public float divide(float a,float b){
        return a/b;
    }

    //设计一个方法  控制计算器计算的流程
    public void calculate(){
        Scanner input = new Scanner(System.in);
        System.out.println("请输入第一个数字");
        String one = input.nextLine();//1
        float a = Float.parseFloat(one);//可能会产生NumberFormatException 1
        //需要一个死循环 while(true){}
        while(true) {
            System.out.println("请输入符号");
            String symbol = input.nextLine();//+ - =
            if(symbol.equals("=")){
                System.out.println("执行完毕");
                break;
            }
            if(!(symbol.equals("+")||symbol.equals("-")||symbol.equals("*")||symbol.equals("/"))){
                System.out.println("输入的符号有误,只能是[ + - * / = ]其中的一个");
                continue;
            }
            System.out.println("请输入第二个数字");
            String two = input.nextLine();//2 3
            //String--->float   Float
            float b = Float.parseFloat(two);
            switch (symbol) {  //为什么在这里判断符号呢?因为你得把所有的数值a和b都输出完毕,再去运行
                case "+":
                    a = this.add(a, b);//第一次运行完毕的结果 存起来 当作第二次开始的a数字//3
                    break;
                case "-":
                    a = this.substact(a, b);
                    break;
                case "*":
                    a = this.multiply(a, b);
                    break;
                case "/":
                    a = this.divide(a, b);
                    break;
            }
            System.out.println(a);
        }
    }
}

test中:

public class Test {
    public static void main(String[] args){
        Calculator c = new Calculator();
        c.calculate();
    }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值