关于方法中的参数类型
**答:方法中的参数类型,一般的有int、String、bool、Double,这些其实是JAVA内置的一些类,因此我们可以得到推论,当我们创建了一个公共的类的时候,我们可以在方法的参数类型上使用该类,比如:
public void S1(People tom){}
这里People是我定义的一个类,传入的是tom,tom是一个对象!**
在方法体内,我们可以使用该类中的方法,操作是:对象名 . 方法名
当参数类型是自定义类型的时候,传入的形参是该类的对象
一般来说,在new该类的对象的时候,我们会传入参数,因为我们会在该类中写类的构造器,即new一个对象的时候,就已经定义了一些变量,而我们的对象指向这些变量的地址
重写和重载的区别
答:重载和重写最大的区别就是,重载是在一个类,重写在不同类。重载时的参数类型个数或者参数至少有一个不同。
多态
先编译类型 在执行类型,编译引用调用方法时,验证对象的动作是否在编译对象中,即方法是否存在同名,如果发现有同名(父类中有这个方法),对象中也有(子类中也有),那么此时就按执行类型来从子类中开始寻找这个方法,在往上找,直到找到同名的方法,找到了之后那么就调用此方法。
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
属性没有重写之说,结果根据编译类型而得出
Base b=s => s指向Sub 因此b也指向Sub =>等于说是Sub有2个名字 一个 叫 b 一个叫s => 因此b的运行类型是Sub 向下转型
构造器的好处
有一点很方便,就是你在调用某个类的方法时,只要你有这个类的构造器,你在创建对象的时候给上参数,那么这些参数你就可以用在该类的方法里面,在主函数你 只用a . 方法名即可,主函数就异常简洁。
instanceof :用来判断运行类型的
父类引用指向子类对象:向上转型
父类索引指向子类对象,向上转型
向下转型等于强类型转换转换成子类
同一个类new出来的对象,地址不同
JAVA 零钱通实例
- 1、先完成显示菜单,并可以通过选择菜单,并给出显示。
- 显示菜单,一般使用do-while,因为菜单总得显示一次,而且始终是一个不停显示菜单得过程,除非你输入指定命令退出菜单。
package objectApp.simplechange;
import java.util.Scanner;
public class SmallChangeSys {
//此函数完成显示菜单,并可以选择菜单,给出相应提示
public static void main(String[] args) {
boolean flag = true;
do {
System.out.println("===============零钱通菜单===============");
System.out.println("\t\t\t1 零钱通明细");
System.out.println("\t\t\t2 收益入账");
System.out.println("\t\t\t3 消费");
System.out.println("\t\t\t4 退出");
System.out.print("请选择(1-4):");
Scanner scan = new Scanner(System.in);
int num = scan.nextInt();
//记录输入得数字,如果是4则flag==false
if (num == 4) {
System.out.print("您确定要退出吗?y/n:");
String exit=scan.next();
if(exit.equals("y")){
flag = false;
}
} else {
switch (num) {
case 1:
System.out.println("===============零钱通明细===============");
//后面在写详细内容
break;
case 2:
System.out.println("===============收益入账===============");
//
break;
case 3:
System.out.println("===============消费===============");
break;
default:
System.out.println("请重新选择(1-4):");
}
}
} while (flag);
System.out.print("您已退出!");
}
}
字符串判断,不能用==
-这里我在写的时候出现了一个问题,即使输入4在输入y后仍然无法退出程序,后来我调试的时候发现,flag一直是true,我就很奇怪了,我明明判断了两个字符串是否相等的啊,怎么还会是true呢,判断代码为:
if(exit=="y"){
flag=false;
}
这里我其实犯了一个低级错误,首先,我们所说的两个字符串是否相等,是指字符串字面量是否相等,如果使用==来判断两个字符串是否相等,那么实际比较的是两个字符串的存储地址(即内存地址)是否相等。这里两者的内存地址一定不同,因此根本就不会进入到判断条件里面去。最后,字符串是否相等要用equals来判断。
- 2、收益入账
主要代码
/*收益入账*/
public void earnSalar(double money) {
String earnings = "收益入账";
balance += money;
details += "\n" + "收益:" + money +"元"+ "\t\t\t\t\t\t" + "日期:" + dateFormat.format(date) + "\t\t" + "余额:" + balance+"元";
System.out.println("收益入账" + "\t\t\t\t日期" + "\t\t\t\t余额");
System.out.println(money + "\t\t" + dateFormat.format(date) + "\t\t" + balance);
}
- 3、消费
/*消费*/
public void consume(String action, double expenditures) {
if (balance > expenditures) {
balance -= expenditures;
details +="\n"+ action + ":" + expenditures + "元\t\t\t\t\t\t" +"日期:"+ dateFormat.format(date) + "\t\t" +"余额:"+ balance+"元";
System.out.println("支出活动" + "\t支出金额" + "\t\t日期\t\t" + "\t\t\t\t余额");
System.out.println(action + "\t\t" + expenditures + "\t\t" + dateFormat.format(date) + "\t\t" + balance);
} else {
System.out.println("您的余额不足!");
}
}
- 4、明细
String details = "===============零钱通明细===============";
这里有人就奇怪了,为什么明细里面没有代码呢,其实如果你仔细看的话,你会发现,在这个项目里面,我运用了字符串的连接这一个知识点,并且在连接的时候,每次都加上一个换行符,来规范输出,前期是这个details是放在类中的,而不是任何方法里,它是一个全局变量,以及上面的余额balance也是全局的变量,因为消费方法里,要用到。
- 5、全部代码,面向对象版
package objectApp.simplechange;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
public class SmallChangeSys {
//此函数完成显示菜单,并可以选择菜单,给出相应提示
double balance = 0;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = new Date();
String details = "===============零钱通明细===============";
public static void main(String[] args) {
SmallChangeSys person = new SmallChangeSys();
person.menu(person);
}
//显示菜单,并且可以选择
public void menu(SmallChangeSys person){
boolean flag = true;
do {
System.out.println("===============零钱通菜单===============");
System.out.println("\t\t\t1 零钱通明细");
System.out.println("\t\t\t2 收益入账");
System.out.println("\t\t\t3 消费");
System.out.println("\t\t\t4 退出");
System.out.print("请选择(1-4):");
Scanner scan = new Scanner(System.in);
int num = scan.nextInt();
//记录输入得数字,如果是4则flag==false
if (num == 4) {
System.out.print("您确定要退出吗?y/n:");
String exit = scan.next();
if (exit.equals("y")) {
flag = false;
}
} else {
switch (num) {
case 1:
/*
* 这里其实一个很重要的思想就是利用字符串的连接,你想要输出全部的订单,只要你进行过操作的,你都要输出。
* 如果运用字符串,那么就该想到字符串的连接,每次进行一步操作,你都把它放到一个字符串里
* 这样你就可以总体输出你做了哪些操作
* 这里我还运用了对象的方法,定义一个类的对象,它就可以调用该类的全部方法
* */
System.out.println(person.details);
break;
case 2:
/*
* 写一个方法,传入一个值,输出操作
* 前提是定义一个全局变量
* 因为这个变量在其他地方也是要用到的
* */
System.out.println("===============收益入账===============");
System.out.print("请输入您的收益金额:");
double money = scan.nextDouble();
person.earnSalar(money);
break;
case 3:
System.out.println("===============消费===============");
System.out.print("请输入您的消费活动:");
String action = scan.next();
System.out.print("请输入您的消费金额:");
double exmoney = scan.nextDouble();
person.consume(action, exmoney);
break;
default:
System.out.println("请重新选择(1-4):");
}
}
} while (flag);
System.out.print("您已退出!");
}
/*收益入账*/
public void earnSalar(double money) {
String earnings = "收益入账";
if(money>=0){
balance += money;
details += "\n" + "收益:" + money +"元"+ "\t\t\t\t\t\t" + "日期:" + dateFormat.format(date) + "\t\t" + "余额:" + balance+"元";
System.out.println("收益入账" + "\t\t\t\t日期" + "\t\t\t\t余额");
System.out.println(money + "\t\t" + dateFormat.format(date) + "\t\t" + balance);
}
else {
System.out.println("您的收益有误,请重新填写!");
}
}
/*消费*/
public void consume(String action, double expenditures) {
if (balance > expenditures) {
balance -= expenditures;
details +="\n"+ action + ":-" + expenditures + "元\t\t\t\t\t\t" +"日期:"+ dateFormat.format(date) + "\t\t" +"余额:"+ balance+"元";
System.out.println("支出活动" + "\t支出金额" + "\t\t日期\t\t" + "\t\t\t\t余额");
System.out.println(action + "\t\t" + expenditures + "\t\t" + dateFormat.format(date) + "\t\t" + balance);
} else {
System.out.println("您的余额不足!");
}
}
}
控制台:
===============零钱通菜单===============
1 零钱通明细
2 收益入账
3 消费
4 退出
请选择(1-4):1
===============零钱通明细===============
===============零钱通菜单===============
1 零钱通明细
2 收益入账
3 消费
4 退出
请选择(1-4):2
===============收益入账===============
请输入您的收益金额:100
收益入账 日期 余额
100.0 2022-02-27 10:37:29 100.0
===============零钱通菜单===============
1 零钱通明细
2 收益入账
3 消费
4 退出
请选择(1-4):2
===============收益入账===============
请输入您的收益金额:50
收益入账 日期 余额
50.0 2022-02-27 10:37:29 150.0
===============零钱通菜单===============
1 零钱通明细
2 收益入账
3 消费
4 退出
请选择(1-4):2
===============收益入账===============
请输入您的收益金额:30000
收益入账 日期 余额
30000.0 2022-02-27 10:37:29 30150.0
===============零钱通菜单===============
1 零钱通明细
2 收益入账
3 消费
4 退出
请选择(1-4):3
===============消费===============
请输入您的消费活动:吃饭
请输入您的消费金额:1500
支出活动 支出金额 日期 余额
吃饭 1500.0 2022-02-27 10:37:29 28650.0
===============零钱通菜单===============
1 零钱通明细
2 收益入账
3 消费
4 退出
请选择(1-4):1
===============零钱通明细===============
收益:100.0元 日期:2022-02-27 10:37:29 余额:100.0元
收益:50.0元 日期:2022-02-27 10:37:29 余额:150.0元
收益:30000.0元 日期:2022-02-27 10:37:29 余额:30150.0元
吃饭:1500.0元 日期:2022-02-27 10:37:29 余额:28650.0元
===============零钱通菜单===============
1 零钱通明细
2 收益入账
3 消费
4 退出
请选择(1-4):4
您确定要退出吗?y/n:y
您已退出!
进程已结束,退出代码0
字符串连接符在瞬时记录中的应用如上。
17个案例
第一个案例
package objectApp.Homework;
public class Homework01 {
//3个Person对象,按age从小到大排序
//使用冒泡排序法
public static void main(String[] args) {
Person[] p=new Person[7];
p[0]=new Person("mike",18,"工程师");
p[1]=new Person("tom",32,"作家");
p[2]=new Person("keyle",22,"导演");
p[3]=new Person("kowe",57,"演员");
p[4]=new Person("mary",38,"洗碗工");
p[5]=new Person("jeck",55,"厨师");
p[6]=new Person("mrick",12,"修电脑");
Homework01 h=new Homework01();
h.bubblingSorting(p);
}
//冒泡排序
public void bubblingSorting(Person [] p){
Person temp=null;
for (int i = 0; i < p.length-1; i++) {
for (int j = 0; j < p.length - 1 - i; j++) {
if(p[j].getAge()>p[j+1].getAge()){
temp=p[j];
p[j]=p[j+1];
p[j+1]=temp;
}
}
}
System.out.println("排序后");
for (int i = 0; i < p.length; i++) {
System.out.println(p[i]);//默认输出的是对象的toString方法,所以不用你.toString了
}
}
}
class Person{
private String name;
private int age;
private String job;
public Person(String name, int age, String job) {
this.name = name;
this.age = age;
this.job = job;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
if(age<=0){
System.out.println("您的年龄输入有误!");
return -1;
}else {
return age;
}
}
public void setAge(int age) {
this.age = age;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", job='" + job + '\'' +
'}';
}
}
总结:
- 对象默认的输出是toString,输出的是一个地址,如果我们想要输出数组中的内容,可以重写toString方法。
- 冒泡排序,作用是交换位置,而不是交换数据,千万不要写p[j].getAge()=p[j+1].getAge();,这样就理解错了。
- 想要限制输入的属性符合你的条件,是在GET方法中体现的,如果不符合你的条件,你就在GET中return一个-1或者erro。
第二个案例
- 写出四种访问修饰符和各自的权限
第三个案例
题目:
package objectApp.Homework;
public class Homework03 {
public static void main(String[] args) {
Teacher t=new Lecturer("张三",18,"讲师",1000);
t.introduce();
t=new Professor("李四",22,"教授",5000);
t.introduce();
t=new AssociateProfessor("王思聪",35,"副教授",3500);
t.introduce();
}
}
//老师类 父类
class Teacher{
private String name;
private int age;
private String post;
private double salary;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPost() {
return post;
}
public void setPost(String post) {
this.post = post;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Teacher(String name, int age, String post, double salary) {
this.name = name;
this.age = age;
this.post = post;
this.salary = salary;
}
public void introduce(){
System.out.println("姓名:"+name+"年龄:"+age+"职称:"+post+"基本工资:"+salary);
}
}
//教授类 子类
class Professor extends Teacher{
public Professor(String name, int age, String post, double salary) {
super(name, age, post, salary);
}
public void introduce(){
System.out.println("姓名:"+getName()+"年龄:"+getAge()+"职称:"+getPost()+"总工资:"+getSalary()*1.3);
}
}
//副教授
class AssociateProfessor extends Teacher{
public AssociateProfessor(String name, int age, String post, double salary) {
super(name, age, post, salary);
}
public void introduce(){
System.out.println("姓名:"+getName()+"年龄:"+getAge()+"职称:"+getPost()+"总工资:"+getSalary()*1.2);
}
}
//讲师
class Lecturer extends Teacher{
public Lecturer(String name, int age, String post, double salary) {
super(name, age, post, salary);
}
public void introduce(){
System.out.println("姓名:"+getName()+"年龄:"+getAge()+"职称:"+getPost()+"总工资:"+getSalary()*1.1);
}
}
- 总结:
- 根据题目,可以看出考的是重写,即在不同的类中重写方法,并且考到了多态,在我们的主函数中,我们并没有创建3个不同的引用名,而是使用了
Teacher t= new 类名
的方法,这样做的好处是显而易见的,它让主函数的代码更加简洁明了,调用不同的对象,我只需要改变引用t
的地址的行了,即声明不同的对象。
第四个案例
package objectApp.Homework;
public class Homework04 {
public static void main(String[] args) {
Employee e=new OrdinaryEmployees("志刚",300,30,1.0);
e.Salary();
e = new Manger("李四", 500, 30, 1.2);
e.Salary();
}
}
class Employee{
private String name;
private double ingleDaySalary;//单日工资
private int day;//工作天数
public Employee(String name, double ingleDaySalary, int day) {
this.name = name;
this.ingleDaySalary = ingleDaySalary;
this.day = day;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getIngleDaySalary() {
return ingleDaySalary;
}
public void setIngleDaySalary(double ingleDaySalary) {
this.ingleDaySalary = ingleDaySalary;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public void Salary(){
double salary=ingleDaySalary*day;
System.out.println("员工工资为:"+salary);
}
}
//部门经理
class Manger extends Employee{
private double grade;
public Manger(String name, double ingleDaySalary, int day,double grade) {
super(name, ingleDaySalary, day);
this.grade=grade;
}
public void Salary(){
double salary=getIngleDaySalary()*getDay()*grade+1000;
System.out.println(getName()+"(部门经理)工资为:"+salary+"元");
}
}
//普通员工
class OrdinaryEmployees extends Employee{
private double grade;
public OrdinaryEmployees(String name, double ingleDaySalary, int day,double grade) {
super(name, ingleDaySalary, day);
this.grade=grade;
}
public double getGrade() {
return grade;
}
public void setGrade(double grade) {
this.grade = grade;
}
public void Salary(){
double salary=getIngleDaySalary()*getDay()*grade;
System.out.println(getName()+"工资为:"+salary+"元");
}
}
- 总结
- 依旧使用了多态创建对象的方法,并且重写了父类的方法。
第五个案例
package objectApp.Homework;
public class Homework05 {
public static void main(String[] args) {
Employee05 e=new Worker("Tom","普通员工",2500);
e.totalSalary();
e=new Peasant("Jake","农民",1500);
e.totalSalary();
e=new Teachers("Mary","教师",2000,12,15);
e.totalSalary();
e=new Scientist("NIko","科学家",5000,10000);
e.totalSalary();
e=new Waiter("Lope","服务员",1500);
e.totalSalary();
}
}
class Employee05 {
private String name;
private String post;
private double salary;
public void totalSalary(){
System.out.println(name+"职称为:"+post+"\t工资为:"+salary);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPost() {
return post;
}
public void setPost(String post) {
this.post = post;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Employee05(String name, String post, double salary) {
this.name = name;
this.post = post;
this.salary = salary;
}
}
class Worker extends Employee05{
public Worker(String name, String post, double salary) {
super(name, post, salary);
}
public void totalSalary(){
System.out.println(getName()+"职称为:"+getPost()+"\t工资为:"+getSalary());
}
}
class Peasant extends Employee05{
public Peasant(String name, String post, double salary) {
super(name, post, salary);
}
public void totalSalary(){
System.out.println(getName()+"职称为:"+getPost()+"\t工资为:"+getSalary());
}
}
class Teachers extends Employee05{
private double Remuneration;//课酬
private int day;
public Teachers(String name, String post, double salary, double remuneration, int day) {
super(name, post, salary);
Remuneration = remuneration;
this.day=day;
}
public double getRemuneration() {
return Remuneration;
}
public void setRemuneration(double remuneration) {
Remuneration = remuneration;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public void totalSalary(){
System.out.println(getName()+"职称为:"+getPost()+"\t工资为:"+(getSalary()+Remuneration*day));
}
}
class Scientist extends Employee05{
private double Yearendbonus;//年终奖
public double getYearendbonus() {
return Yearendbonus;
}
public void setYearendbonus(double yearendbonus) {
Yearendbonus = yearendbonus;
}
public Scientist(String name, String post, double salary, double yearendbonus) {
super(name, post, salary);
Yearendbonus = yearendbonus;
}
public void totalSalary(){
System.out.println(getName()+"职称为:"+getPost()+"\t工资为:"+(getSalary()+Yearendbonus));
}
}
class Waiter extends Employee05{
public Waiter(String name, String post, double salary) {
super(name, post, salary);
}
public void totalSalary(){
System.out.println(getName()+"职称为:"+getPost()+"\t工资为:"+getSalary());
}
}
- 总结:
- 父类写构造方法,子类就可以直接super使用,就不用在声明那么多属性了。
第六个案例
声明:以下都是以子类视角描述
- this先找本类的成员,如果本类没有那么它才会去上它的父类那里寻找,但是只能访问权限够的。
- super只能访问父类中公有的成员,如果直接父类没有,它会继续往父类的父类找。
第七个案例
总结:
- 只要new子类对象,必先初始化父类的构造器。
- super会在父类中寻找同名的方法或属性。
- this会在子类中先寻找相同的成员,找不到后在去父类寻找。
- this(“hello”)是从子类本身开始找含一个字符串参数的构造器,如果没有才会在父类寻找,和super唯一的不同就是起始位置不同。