前提:
之前学习类的内部成员Person
1.属性—静态描述类的特征(变量 存值) name
2.方法—动态描述类的行为(做事情) eat
现在补充两个成员
3.构造方法—用来创建当前类的对象(方法 很特殊)
4.程序块(代码块)—理解为就是一个方法(非常特殊的 无修饰符无参数无返回值无名字)
现在说:类中的第三个成员:
构造方法—做事情
权限修饰符 与类名一致的方法名 (参数列表) [抛出异常可有可无]{
一件事情 创建一个对象(当前类Person)
返回对象;
}
假设有一个类Person,那么构造函数如何使用?看下面的代码:
Person p = new Person
这不是和以前定义一个对象一样吗?对就是一样的,其实以前我们虽然没有定义构造函数,也能定义对象,是因为如果不自己定义一个构造函数的话,编译器会自动默认为我们定义了一个构造函数。
假设自己定义了下面的构造函数,那么原来的默认无参数的构造函数会被覆盖。
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(){ } //重载一个无参数的构造函数
那么就会思考一个问题?为什么使用构造函数?
如果没有构造函数:我们定义给对象赋予属性的时候,往往是:
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;
//返回了创建的这个对象空间的引用
}
类的第四个成员—程序块(代码块)
{
}
例子:
{
System.out.println("我也是一个块 哈哈");
}
{
System.out.println("我是一个普通的程序块");
}
{
System.out.println("我又是一个块");
}
构造方法中,属性与变量重名,必须需要一个代替词,代替对象
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类及其中方法的使用
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
}
}//这样就可以正常运行了。
任务:
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();
}
}