07_面向对象(成员变量和局部变量区别、类作为形式参数的问题、匿名对象、封装、private关键字、this关键字、构造方法、成员方法、static关键字、静态变量和成员变量、main方法)_02
7:构造方法(掌握)
(1)作用:用于对对象的数据进行初始化
(2)格式:
A:方法名和类名相同
B:没有返回值类型,连void都不能有
C:没有返回值
思考题:构造方法中可不可以有return语句呢?
可以。而是我们写成这个样子就OK了:return;
其实,在任何的void类型的方法的最后你都可以写上:return;
(3)构造方法的注意事项
A:如果我们没写构造方法,系统将提供一个默认的无参构造方法
B:如果我们给出了构造方法,系统将不再提供默认构造方法
如果这个时候,我们要使用无参构造方法,就必须自己给出。
推荐:永远手动自己给出无参构造方法。
(4)给成员变量赋值的方式
A:setXxx()
B:带参构造方法
(5)标准案例
class Student {
private String name;
private int age;
public Student(){}
public Student(String name,int age) {
this.name = name;
this.age = age;
}
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;
}
}
测试:
class StudentDemo {
public static void main(String[] args) {
//方式1
Student s1 = new Student();
s1.setName("林青霞");
s1.setAge(27);
System.out.println(s1.getName()+"---"+s1.getAge());
//方式2
Student s2 = new Student("刘意",30);
System.out.println(s2.getName()+"---"+s2.getAge());
}
}
ConstructDemo.java
/* 构造方法: 给对象的数据进行初始化 格式: A:方法名与类名相同 B:没有返回值类型,连void都没有 C:没有具体的返回值 */ class Student { private String name; //null private int age; //0 public Student() { System.out.println("这是构造方法"); } } class ConstructDemo { public static void main(String[] args) { //创建对象 Student s = new Student(); System.out.println(s); //Student@e5bbd6 } }
ConstructDemo2.java
/* 我们一直在使用构造方法,但是,我们确没有定义构造方法,用的是哪里来的呢? 构造方法的注意事项: A:如果我们没有给出构造方法,系统将自动提供一个无参构造方法。 B:如果我们给出了构造方法,系统将不再提供默认的无参构造方法。 注意:这个时候,如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法 给成员变量赋值有两种方式: A:setXxx() B:构造方法 */ class Student { private String name; private int age; public Student() { //System.out.println("我给了,你还给不"); System.out.println("这是无参构造方法"); } //构造方法的重载格式 public Student(String name) { System.out.println("这是带一个String类型的构造方法"); this.name = name; } public Student(int age) { System.out.println("这是带一个int类型的构造方法"); this.age = age; } public Student(String name,int age) { System.out.println("这是一个带多个参数的构造方法"); this.name = name; this.age = age; } public void show() { System.out.println(name+"---"+age); } } class ConstructDemo2 { public static void main(String[] args) { //创建对象 Student s = new Student(); s.show(); System.out.println("-------------"); //创建对象2 Student s2 = new Student("林青霞"); s2.show(); System.out.println("-------------"); //创建对象3 Student s3 = new Student(27); s3.show(); System.out.println("-------------"); //创建对象4 Student s4 = new Student("林青霞",27); s4.show(); } }
成员方法:
StudentDemo.java
/* 类的组成:成员变量,成员方法 今天我们又加入了一个新的成员:构造方法。 以后再提类的组成: 成员变量 构造方法 成员方法 根据返回值: void类型 非void类型 形式参数: 空参方法 非空参方法 */ class Student { public String getString() { return "helloworld"; } public void show() { System.out.println("show"); } public void method(String name) { System.out.println(name); } public String function(String s1,String s2) { return s1+s2; } } class StudentDemo { public static void main(String[] args) { //创建对象 Student s = new Student(); //调用无参无返回值方法 s.show(); //调用无参有返回值方法 String result = s.getString(); System.out.println(result); //调用带参无返回值的方法 s.method("林青霞"); //调用带参带返回值的方法 String result2 = s.function("hello","world"); System.out.println(result2); } }/* 类的组成:成员变量,成员方法 今天我们又加入了一个新的成员:构造方法。 以后再提类的组成: 成员变量 构造方法 成员方法 根据返回值: void类型 非void类型 形式参数: 空参方法 非空参方法 */ class Student { public String getString() { return "helloworld"; } public void show() { System.out.println("show"); } public void method(String name) { System.out.println(name); } public String function(String s1,String s2) { return s1+s2; } } class StudentDemo { public static void main(String[] args) { //创建对象 Student s = new Student(); //调用无参无返回值方法 s.show(); //调用无参有返回值方法 String result = s.getString(); System.out.println(result); //调用带参无返回值的方法 s.method("林青霞"); //调用带参带返回值的方法 String result2 = s.function("hello","world"); System.out.println(result2); } }
StudentTest.java
/* 一个标准代码的最终版。 学生类: 成员变量: name,age 构造方法: 无参,带两个参 成员方法: getXxx()/setXxx() show():输出该类的所有成员变量值 给成员变量赋值: A:setXxx()方法 B:构造方法 输出成员变量值的方式: A:通过getXxx()分别获取然后拼接 B:通过调用show()方法搞定 */ class Student { //姓名 private String name; //年龄 private int age; //构造方法 public Student() { } public Student(String name,int age) { this.name = name; this.age = age; } 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 void show() { System.out.println(name+"---"+age); } } //测试类 class StudentTest { public static void main(String[] args) { //方式1给成员变量赋值 //无参构造+setXxx() Student s1 = new Student(); s1.setName("林青霞"); s1.setAge(27); //输出值 System.out.println(s1.getName()+"---"+s1.getAge()); s1.show(); System.out.println("----------------------------"); //方式2给成员变量赋值 Student s2 = new Student("刘意",30); System.out.println(s2.getName()+"---"+s2.getAge()); s2.show(); } }
PhoneTest.java
/* 标准的手机类练习 手机类: 成员变量:brand,price,color 构造方法:无参构造 成员方法:getXxx()/setXxx() */ //定义手机类 class Phone { //品牌 private String brand; //价格 private int price; //颜色 private String color; //无参构造方法 public Phone() {} //getXxx()和setXxx()方法 public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } } //手机测试类 class PhoneTest { public static void main(String[] args) { //创建对象 Phone p = new Phone(); //给成员变量赋值 p.setBrand("诺基亚"); p.setPrice(199); p.setColor("土豪金"); //获取值 System.out.println(p.getBrand()+"---"+p.getPrice()+"---"+p.getColor()); } }
8:代码:Student s = new Student();做了哪些事情?(理解)
(1)把Student.class文件加载到内存
(2)在栈内存为s开辟空间
(3)在堆内存为学生对象申请空间
(4)给学生的成员变量进行默认初始化。null,0
(5)给学生的成员变量进行显示初始化。林青霞,27
(6)通过构造方法给成员变量进行初始化。刘意,30
(7)对象构造完毕,把地址赋值给s变量
9:面向对象的练习题(掌握)
(1)标准的手机类的定义和测试
(2)Demo类有求和方法,Test类进行测试。
什么时候定义成员变量?
当该变量是用来描述一个类的时候。
(3)长方形案例
(4)员工案例
(5)MyMath案例(自己提供加减乘除并测试)
/* 定义一个类Demo,其中定义一个求两个数据和的方法, 定义一个测试了Test,进行测试。 变量什么时候定义为成员变量: 如果这个变量是用来描述这个类的信息的,那么,该变量就应该定义为成员变量。 变量到底定义在哪里好呢? 变量的范围是越小越好。因为能及时的被回收。 */ //方式1 /* class Demo { public int sum() { int a = 10; int b = 20; int c = a + b; return c; } } */ //方式1满足了我们的要求,但是不好。 //因为参与操作的数据现在是固定的。 //方式2 /* class Demo { public int sum(int a,int b) { return a + b; } } */ //方式2可以满足我们的要求,但是呢我们学习过来面向对象的思想。 //我就再想,a,b可不可以定义为成员变量呢? //如果可以,我们再改进一版 class Demo { int a; int b; public int sum() { return a + b; } } //虽然这种方式可以,并且好像是符合了面向对象的思想。 //但是不好。 //因为我们曾经说过:类是一组相关的属性和行为的集合。 //并且类是通过事物转换过来的 //而类中的成员变量就是事物的属性 //属性是用来描述事物的 //同理:成员变量其实是用来描述类的。 //测试类 class Test { public static void main(String[] args) { //创建对象 //方式1测试 /* Demo d = new Demo(); System.out.println(d.sum()); */ //方式2测试 /* Demo d = new Demo(); int a = 10; int b = 20; System.out.println(d.sum(a,b)); */ //方式3测试 Demo d = new Demo(); d.a = 10; d.b = 20; System.out.println(d.sum()); } }
长方形案例:
/* 定义一个长方形类,定义 求周长和面积的方法, 然后定义一个测试了Test2,进行测试。 长方形的类: 成员变量: 长,宽 成员方法: 求周长:(长+宽)*2; 求面积:长*宽 注意: import必须出现在所有的class前面。 */ import java.util.Scanner; class ChangFangXing { //长方形的长 private int length; //长方形的宽 private int width; public ChangFangXing(){} //仅仅提供setXxx()即可 public void setLength(int length) { this.length = length; } public void setWidth(int width) { this.width = width; } //求周长 public int getZhouChang() { return (length + width) * 2; } //求面积 public int getArea() { return length * width; } } class Test2 { public static void main(String[] args) { //创建键盘录入对象 Scanner sc = new Scanner(System.in); System.out.println("请输入长方形的长:"); int length = sc.nextInt(); System.out.println("请输入长方形的宽:"); int width = sc.nextInt(); //创建对象 ChangFangXing cfx = new ChangFangXing(); //先给成员变量赋值 cfx.setLength(length); cfx.setWidth(width); System.out.println("周长是:"+cfx.getZhouChang()); System.out.println("面积是:"+cfx.getArea()); } }
EmployeeTest.java
/* 需求: 定义一个员工类,自己分析出几个成员, 然后给出成员变量,构造方法,getXxx()/setXxx()方法, 以及一个显示所有成员信息的方法。并测试。 分析: 员工 成员变量: 员工编号,姓名,年龄 构造方法: 无参构造方法 成员方法: getXxx()/setXxx() show(); */ class Employee { //员工编号 private String employeeId; //姓名 private String name; //年龄 private int age; //构造方法 public Employee() {} //getXxx()/setXxx() public String getEmployeeId() { return employeeId; } public void setEmployeeId(String employeeId) { this.employeeId = employeeId; } 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 void show() { System.out.println("员工编号是:"+employeeId+"的这个人是:"+name+"的年龄是:"+age); } } class EmployeeTest { public static void main(String[] args) { //创建对象 Employee e = new Employee(); //给成员变量赋值 e.setEmployeeId("czbk9527"); e.setName("唐伯虎"); e.setAge(18); //获取数据 //System.out.println(e.getEmployeeId()+"---"+e.getName()+"---"+e.getAge()); //我们在Employee类中定义了一个show方法。所以,我们改进一下,使用show方法 e.show(); } }
MyMathTest.java
/* 定义一个类MyMath,提供基本的加减乘除功能,然后进行测试。 */ import java.util.Scanner; class MyMath { //加法功能 public int add(int a,int b) { return a + b; } //减法功能 public int sub(int a,int b) { return a - b; } //乘法功能 public int mul(int a,int b){ return a * b; } //除法功能 public int div(int a,int b) { return a / b; } } //测试类 class MyMathTest { public static void main(String[] args) { //创建键盘录入对象 Scanner sc = new Scanner(System.in); System.out.println("请输入第一个操作数:"); int firstNumber = sc.nextInt(); System.out.println("请输入第二个操作数:"); int secondNumber = sc.nextInt(); //创建MyMath对象,并使用 MyMath mm = new MyMath(); System.out.println("加法结果:"+mm.add(firstNumber,secondNumber)); System.out.println("减法结果:"+mm.sub(firstNumber,secondNumber)); System.out.println("乘法结果:"+mm.mul(firstNumber,secondNumber)); System.out.println("除法结果:"+mm.div(firstNumber,secondNumber)); } }
10:static关键字(理解)
(1)静态的意思。可以修饰成员变量和成员方法。
(2)静态的特点:
A:随着类的加载而加载
B:优先与对象存在
C:被类的所有对象共享
这其实也是我们判断该不该使用静态的依据。
举例:饮水机和水杯的问题思考
D:可以通过类名调用
既可以通过对象名调用,也可以通过类名调用,建议通过类名调用。
(3)静态的内存图
静态的内容在方法区的静态区
(4)静态的注意事项;
A:在静态方法中没有this对象
B:静态只能访问静态(代码测试过)
(5)静态变量和成员变量的区别
A:所属不同
静态变量:属于类,类变量
成员变量:属于对象,对象变量,实例变量
B:内存位置不同
静态变量:方法区的静态区
成员变量:堆内存
C:生命周期不同
静态变量:静态变量是随着类的加载而加载,随着类的消失而消失
成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失
D:调用不同
静态变量:可以通过对象名调用,也可以通过类名调用
成员变量:只能通过对象名调用
(6)main方法是静态的
public:权限最大
static:不用创建对象调用
void:返回值给jvm没有意义
main:就是一个常见的名称。
String[] args:可以接收数据,提供程序的灵活性
格式:java MainDemo hello world java
java MainDemo 10 20 30
PersonDemo.java
/* 定义一个人类 姓名和年龄都是变化的,这个我能接收,因为每个人的姓名和年龄是不同的。 但是,我们现在选取的几个人都是中国人,他们的国籍是一样的。 一样的国籍,我每次创建对象,在堆内存都要开辟这样的空间, 我就觉得有点浪费了。怎么办呢? 针对多个对象有共同的这样的成员变量值的时候, Java就提高了一个关键字来修饰:static。 */ class Person { //姓名 String name; //年龄 int age; //国籍 //String country; static String country; public Person(){} public Person(String name,int age) { this.name = name; this.age = age; } public Person(String name,int age,String country) { this.name = name; this.age = age; this.country = country; } public void show() { System.out.println("姓名:"+name+",年龄:"+age+",国籍:"+country); } } class PersonDemo { public static void main(String[] args) { //创建对象1 Person p1 = new Person("邓丽君",16,"中国"); p1.show(); //创建对象2 //Person p2 = new Person("杨幂",22,"中国"); //p2.show(); Person p2 = new Person("杨幂",22); p2.show(); //创建对象3 //Person p3 = new Person("凤姐",20,"中国"); //p3.show(); Person p3 = new Person("凤姐",20); p3.show(); p3.country = "美国"; p3.show(); p1.show(); p2.show(); } }
StudentDemo.java
/* static的特点:(它可以修饰成员变量,还可以修饰成员方法) A:随着类的加载而加载 回想main方法。 B:优先于对象存在 C:被类的所有对象共享 举例:咱们班级的学生应该共用同一个班级编号。 其实这个特点也是在告诉我们什么时候使用静态? 如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。 举例: 饮水机(用静态修饰) 水杯(不能用静态修饰) D:可以通过类名调用 其实它本身也可以通过对象名调用。 推荐使用类名调用。 静态修饰的内容一般我们称其为:与类相关的,类成员 */ class Student { //非静态变量 int num = 10; //静态变量 static int num2 = 20; } class StudentDemo { public static void main(String[] args) { Student s = new Student(); System.out.println(s.num); System.out.println(Student.num2); System.out.println(s.num2); } }
TeacherDemo.java
/* static关键字注意事项 A:在静态方法中是没有this关键字的 如何理解呢? 静态是随着类的加载而加载,this是随着对象的创建而存在。 静态比对象先存在。 B:静态方法只能访问静态的成员变量和静态的成员方法 静态方法: 成员变量:只能访问静态变量 成员方法:只能访问静态成员方法 非静态方法: 成员变量:可以是静态的,也可以是非静态的 成员方法:可是是静态的成员方法,也可以是非静态的成员方法。 简单记: 静态只能访问静态。 */ class Teacher { public int num = 10; public static int num2 = 20; public void show() { System.out.println(num); //隐含的告诉你访问的是成员变量 System.out.println(this.num); //明确的告诉你访问的是成员变量 System.out.println(num2); //function(); //function2(); } public static void method() { //无法从静态上下文中引用非静态 变量 num //System.out.println(num); System.out.println(num2); //无法从静态上下文中引用非静态 方法 function() //function(); function2(); } public void function() { } public static void function2() { } } class TeacherDemo { public static void main(String[] args) { //创建对象 Teacher t = new Teacher(); t.show(); System.out.println("------------"); t.method(); } }
Static的内存图解:
MainDemo.java
/* main方法的格式讲解: public static void main(String[] args) {...} public:公共的,访问权限是最大的。由于main方法是被jvm调用,所以权限要够大。 static:静态的,不需要创建对象,通过类名就可以。方便jvm的调用。 void:因为我们曾经说过,方法的返回值是返回给调用者,而main方法是被jvm调用。你返回内容给jvm没有意义。 main:是一个常见的方法入口。我见过的语言都是以main作为入口。 String[] args:这是一个字符串数组。值去哪里了? 这个东西到底有什么用啊?怎么给值啊? 这个东西早期是为了接收键盘录入的数据的。 格式是: java MainDemo hello world java */ class MainDemo { public static void main(String[] args) { //System.out.println(args); //[Ljava.lang.String;@175078b //System.out.println(args.length); //0 //System.out.println(args[0]); //ArrayIndexOutOfBoundsException //接收数据后 System.out.println(args); System.out.println(args.length); //System.out.println(args[0]); for(int x=0; x<args.length; x++) { System.out.println(args[x]); } } }