详细研究如何去定义一个类。
1. 一个类由三个部分组成。这三个部分并不是全部必须的。
在编写类之前,要先设计类:数据(用成员变量来表示),和对这些数据的操作(用成员方法来表示)。
class 类名{ //1.成员变量 //3.构造器(构造方法) -> 其中一个重要作用,是对成员变量进行初始化 //2.成员方法 —> 用来操作本类中的成员变量/或者像一个普通的方法(函数)一样 }
2.成员变量。
也叫"字段"。它的定义和一般变量是一样的。
成员变量也叫"实例变量",如果不明确赋值的话,会自带一个默认的值。
成员变量:遵循标识符的命名规则;驼峰命名法,首字母小写:望文生义。
class C{ byte byteVar; byte shortVar; int intVar; long longVar; float floatVar; double doubleVar; char charVar; boolean booleanVar; String string; } public class Demo{ public static void main(String[] args){ C c = new C(); System.out.println(c.byteVar); System.out.println(c.shortVar); System.out.println(c.intVar); System.out.println(c.longVar); System.out.println(c.floatVar); System.out.println(c.doubleVar); System.out.println(c.charVar); System.out.println(c.booleanVar); System.out.println(c.string); } }
3.成员方法。
语法格式 void |数据类型 方法名称(参数列表){ //方法体 }
3.1方法命名:遵循标识符的命名规则;驼峰命名法,首字母小写:望文生义。方法的命名:动词+名词。
3.2方法名称后面,必须紧跟一对小括号。小括号内,可以有参数(有1个或多个。如果有多个的话,称为参数列表,用逗号
分隔),也可以没有参数。
3.3方法命名前,要指定该方法返回数据类型。(既可以是原始数据类型,也可以是自定义数据类型,还可以是数组)。
如果该方法的代码调用后,不要求有返回值,那么,必须用void关键字指明。
如果该方法的代码调用后,有返回值,那么,在方法体内(花括号内),必须要有"return 返回数据"语句,并且返回数据的类型,要和方法名前指定的数据类型保持一
致。
3.4对方法的调用:通过方法名称(后跟小括号)的方式调用。
3.5方法声明中的参数,为局部变量。局部变量和成员变量的区别:
局部变量的生命周期(变量的作用域),仅限于从它声明开始,到所在方法结束。
3.6参数传递中的"值传递"和"引用传递"。
3.7当一个类中有多个同名的方法、但方法签名不同时,称为"方法重载",又叫"动态方法调用"。
方法签名 ->方法签名 = 方法名称 + 参数数量和类型/顺序。
//定义一个小计算器类 class Calculate{ //加法运算 int add(int number1, int number2){ //这里定义的参数称为"形参" int result = number1 + number2; return result; } //对两个整数值进行交换 void swap(int number1, int number2){ int temp; temp = number1; number1 = number2; number2 = temp; } void swap(int[] numbers){ int temp; temp = number[0]; number[0] = number[1]; number[1] = temp; } } public class Demo{ public static void main(String[] args){ int a = 3, b = 5; Calculate cal = new Calculate(); int addResult = cal.add(a, b); //这里传进去的a和b成称为"实参" System.out.println(addResult); System.out.println("交换方法调用前:a=" + a + ",b=" + b); //a = 3,b = 5 cal.swap(a, b); System.out.println("交换方法调用后:a=" + a + ",b=" + b); //a = ?,b = ? -> 值传递 int[] intArray = {3, 5}; System.out.println("交换方法调用前:" + intArray[0] + "," + intArray[1]); cal.swap(intArray); System.out.println("交换方法调用后:" + intArray[0] + "," + intArray[1]);//a = ?,b = ? -> 引用传递 } }
//需求:保存多个学生的信息。(使用成员方法) class Student{ //成员变量 String stuName; //学号字段 int stuId; //姓名字段 int stuAge; //年龄字段 //成员方法 //自我介绍 void selfinfo(){ System.out.println("我叫" + stuName + ",我的学号是" + stuId + ",我的年龄是" + stuAge); } } public class Demo{ public static void main(String[] args){ //1.定义一个Student类型的数组,他只能存入Studnet类型的变量 Student[] stus = new Student[2]; //2.创建并保存第一个学生信息 Student stu01 = new Student(); stu01.stuName = "张三"; stu01.stuId = 111; stu01.stuAge = 18; stus[0] = stu01; //3.创建并保存第二个学生信息 Student stu02 = new Student(); stu02.stuName = "李四"; stu02.stuId = 222; stu02.stuAge = 19; stus[1] = stu02; //for-each遍历数组 for(Student stu : stus){ System.out.println("学号:" + stu.stuId + " 姓名:" + stu.stuName + " 年龄:" + stu.stuAge); } System.out.println("--------------------------------------"); //普通for循环 for(int i = 0;i < stus.length;i++){ Student stu = stus[i]; //System.out.println("学号:" + stu.stuId + " 姓名:" + stu.stuName + " 年龄:" + stu.stuAge); stu.selfinfo();//对对象中方法的调用 } } }
3.8 可变参数:参数的数量是可变的。
1)可变参数,必须是位于参数列表中的最后一个。
2)可变数量:0、1或多个。
3)可变数量,是作为数组进行处理的。
//定义一个小计算器类 class Calculate{ //加法运算 int add(int... numbers){ //使用可变参数 int result = 0; for(int i=0;i<numbers.length;i++){ result = result + numbers[i]; } return result; } } public class Demo{ public static void main(String[] args){ Calculate cal = new Calculate(); System.out.println(cal.add()); System.out.println(cal.add(1)); System.out.println(cal.add(1,1)); System.out.println(cal.add(1,1,1)); } }
4. 变量的作用域。
4.1 在一个类中,有三个地方可以定义变量(三种变量):类的字段部分(成员变量)、方法的参数变量(局部变量)、方法内声明的变量(局部变量)。
4.2 如果局部变量和成员变量同名的情况下,局部变量屏蔽成员变量。
4.3 局部变量,它的作用范围,是从声明它的地方开始,到方法的结束。
4.4 成员变量定义的位置不关紧,它的作用域范围总是在整个内部类。
4.5 所以,好的做法是,尽可能的不要让局部变狼与成员变量同名。
class VarScope{ int number = 0; //成员变量 void write(){ System.out.println(number); } void write(int number){ //参数变量(局部变量) System.out.println(number); } void writeNumber(){ System.out.println(number); int number = 3; //局部变量,它的作用范围,是从声明它的地方开始,到方法的结束。 System.out.println(number); } } public class Demo{ public static void main(String[] args){ VarScope vs = new VarScope(); vs.write(); //? vs.write(5); //? -> 如果局部变量和成员变量同名的情况下,局部变量屏蔽成员变量 vs.writeNumber(); //? ? } }
5. this关键字
但是,有的时候,局部变量又最好是和成员变量同名。
在局部变量屏蔽成员变量的情况下,如果想要绕开这种屏蔽,能访问到成员变量,需要使用this关键字。
6. 属性
实际上,属性不是字段。只有提供了get方法的字段,才称为属性。
//什么情况下,局部变量最好和成员变量同名 class Student{ //成员变量(字段) private String stuId; private String stuName; private int stuAge; //set方法:set开头,后跟字段的名字,首字母变成大写 //这些setter、getter方法,称为"读写器" public void setStuId(String stuId){ this.stuId = stuId; } //把"get"去掉后面首字母换成小写,叫做"属性" //有一个属性叫"stuId" public String getStuId(){ return this.stuId; } public void setStuName(String stuName){ this.stuName = stuName; } //有一个属性叫"stuName" public String getStuName(){ return this.stuName; } public void setStuAge(int stuAge){ if(stuAge<18) this.stuAge = 18; else this.stuAge = stuAge; } //有一个属性叫"stuAge" public int getStuAge(){ return this.stuAge; } //有一种属性叫"angthing" public String getAnything(){ return "anything"; } } public class Demo{ public static void main(String[] args){ Student zhangsan = new Student(); //zhangsan.StuId="112"; //zhangsan.StuName="张三"; //zhangsan.StuAge=18; zhangsan.setStuId("111"); zhangsan.setStuName("张三"); zhangsan.setStuAge(18); System.out.println(zhangsan.getStuId()); System.out.println(zhangsan.getStuName()); System.out.println(zhangsan.getStuAge()); } }
7. 构造器
7.1 构造器,也叫构造方法。其名称必须和类名相同,后跟方法的小括号,再后跟方法体花括号。
7.2 构造方法也可以重载。
7.3 构造器的主要作用:对成员变量进行初始化、加载资源、……
7.4 构造器的使用:在创建类的实例对象时,使用new运行符,调用构造器,来创建实例,申请空间。
通过构造实例对象时,传递的构造器参数,来对成员变量进行初始化。
class Student{ //成员变量 private String stuId; private String stuName; private int stuAge; //构造器(构造方法) Student(){ System.out.println("无参构造器"); } Student(String stuId){ this.stuId = stuId; System.out.println("1个参数构造器"); } Student(String stuId, String stuName){ this.stuId = stuId; this.stuName = stuName; System.out.println("2个参数构造器"); } Student(String stuId, String stuName, int stuAge){ this.stuId = stuId; this.stuName = stuName; this.stuAge = stuAge; System.out.println("3个参数构造器"); } //读写方法:get和set //... } public class Demo{ public static void main(String[] args){ Student stu = new Student(); Student stu01 = new Student("111"); Student stu02 = new Student("112","张三"); Student stu03 = new Student("113","李四",18); } }
7.5 通过this关键字调用同一对象中的其他构造器。
class Student{ //成员变量 private String stuId; private String stuName; private int stuAge; //构造器(构造方法) Student(){ System.out.println("无参构造器"); } Student(String stuId){ System.out.println(this.stuId); this.stuId = stuId; System.out.println("1个参数构造器"); System.out.println(this.stuId); } Student(String stuId, String stuName){ this(stuId); //调用当前对象中带一个参数的构造器 this.stuName = stuName; System.out.println("2个参数构造器"); } Student(String stuId, String stuName, int stuAge){ this(stuId,stuName); if(stuAge < 18) this.stuAge = 18; else this.stuAge = stuAge; System.out.println("3个参数构造器"); } //读写方法:get和set //... } public class Demo{ public static void main(String[] args){ Student stu = new Student("111","三"); // Student stu01 = new Student("111"); // Student stu02 = new Student("112","张三"); // Student stu03 = new Student("113","李四",18); } }
7.6 如果在定义类时,不明确制定一个构造器,那么编译器在编译时,会自动的添加一个空的默认的构造器
但是,一旦你指定了一个构造器,那么,编译器就不会再插入默认的构造器了。