【类与对象、封装、构造方法】
面向对象和面向过程的区别:
面向对象:要实现一个功能的时候不关心过程,调用一个类让他帮我们完成。三个特征:封装、继承、多态
面向过程:要实现一个功能的话亲自动手一步一步实现。
前者相当于指挥者后面是执行者。
类和对象的区别
类是一类事物的模板,是对现实事物的抽象描述。使用成员变量描述事物的属性,成员方法描述成员的行为/功能。
对象是类的一个具体的实例;
创建对象的内存解释
假设定义了这样的一个类,并且在main中实例化了两个对象,我们来看内存中是怎样实现的。
//persion类
public class Persion {
String name;
int age;
//成员方法
public void eat(){
System.out.println(name+"吃了");
}
public void sleep(){
System.out.println(name+"睡了");
}
public void hit(){
System.out.println(name+"打完了");
}
}
//主类
public class Test_Persion {
public static void main(String[] args) {
Persion p = new Persion();//共三步,第一步Persion p在栈中执行。
//第二步new Persion()在堆中申请到空间,第三步把地址赋值给引用变量p。
p.name = "柳岩";//p根据给的地址找到name变量将原来的默认的null改为"柳岩"
p.age = 38;//和上面类似
System.out.println(p.name);
System.out.println(p.age);
p.eat();//p根据地址到堆中找到eat()标记,然后根据标记到了方法区调用eat()方法进栈。执行结束后弹栈
p.sleep();//同上
p.hit();//同上
Persion p2 = new Persion();//和上边差不多只不过是重新在堆中申请了一个新的空间
p2.name = "唐嫣";
p2.age = 28;
System.out.println(p2.name);
System.out.println(p2.age);
p2.eat();//再次调用方法进栈。
p2.sleep();
p2.hit();
}
}
注意:定义的方法在堆中只是写了一个标记,如果要调用它他,要先根据标记到方法区调入此方法入栈,执行结束后弹栈。
成员变量和局部变量的区别
- 作用域不同
- 默认值不同,成员变量有默认值,局部变量没有
- 内存中的位置不同,成员变量随着对象进入堆内存中,局部变量随方法进入栈内存中。
变量访问的就近原则
//Persion类
public class Persion {
String name;
int age;
//eat方法中打印age会是哪个值?
public void eat(){
int age = 10;
System.out.println(age);
System.out.println(this.age);
}
}
答案是打印的10,也就是方法中的Age,因为变量的就近原则,先访问局部变量然后访问类中的成员变量。
private修饰符的作用
他的作用就是保护所修饰的变量/方法不被类以外的外部访问。如果要对它进行访问只能通过方法来访问,对他的限制也只能通过方法。下面的例子是对年龄进行限制。
//Persion类
public class Persion {
private String name;
private int age;
//设置姓名
public void setName(String name){
this.name = name;
}
//返回姓名
public String getName(){
return name;
}
//设置年龄 通过方法对他进行限制
public void setAge(int age){
if (age<0||age>200) {
return;
}
this.age = age;
}
//返回年龄
public int getAge(){
return age;
}
}
this的含义
-
this只能在方法中使用
-
this代表当前对象的引用。当前对象是指:谁调用了这个方法,谁就是当前对象。
-
它是个一地址值 。
封装的概念
封装就是隐藏实现细节(提供private),提供公共的访问方式(get/set方法)。
封装有一个原则就是如果要访问类里的成员变量必须要提供公共的方法来进行访问,不能直接访问。
构造方法
-
构造方法就是创建对象时调用的方法。
-
构造方法的作用就是:对象被创建后为它的成员变量赋初始值
-
构造方法的方法名和类名相同,不需要返回值,也不需要写返回类型。
-
可以有无数个构造方法,但是一般来说带参数的只是用来初始化成员变量。
标准代码——Java Bean的具体例子:
public class Persion {
//定义私有成员变量
private String name;
private int age;
//空参构造方法 必须有!
public Persion(){
System.out.println("这是空参构造");
}
//满参构造方法,可有可无
public Persion(String name,int age){
this.name = name;
this.age = age;
}
//set方法必须有
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
//get方法必须有
public String getName(){
return name;
}
public int getAge(){
return age;
}
}
注意事项
- 空参的构造方法必须有,因为后面可以创建对象不用初始化。
- 满参的构造方法可有可无
- set方法和get方法必须有,因为创建完成后重新更改值的时候必须用set。获取私有成员必须用get方法。
- Java Bean必须有空参构造、私有成员变量、get/set方法。可以不写满参构造
- Java Bean可以不写空参构造,默认就有一个。
- IDEA可以使用快捷键生成构造方法和get/set方法。
练习
手机类如下:
public class Phone {
private String brand;
private String colour;
private double price;
//无参构造
public Phone() { }
//满参构造
public Phone(String brand, String colour, double price) {
this.brand = brand;
this.colour = colour;
this.price = price;
}
//get和set方法
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColour() {
return colour;
}
public void setColour(String colour) {
this.colour = colour;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
//-----------自定义的方法
//打电话
public void call(){
System.out.println(brand+"手机 价格"+price+"颜色是"+colour+"打电话了");
}
//发短信
public void sendMessage(){
System.out.println(brand+"手机 价格"+price+"颜色是"+colour+"发短信了");
}
}
测试类
import java.util.ArrayList;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//创建集合存储
ArrayList<Phone> p = new ArrayList<>();
addPhone(p);
//遍历集合
printPhone(p);
}
//遍历集合并且调用方法
public static void printPhone(ArrayList<Phone> p) {
for (int i = 0; i < p.size(); i++) {
String brand = p.get(i).getBrand();
String colour = p.get(i).getColour();
double price = p.get(i).getPrice();
System.out.println("第"+(i+1)+"个手机的品牌是"+brand);
System.out.println("第"+(i+1)+"个手机的颜色是"+colour);
System.out.println("第"+(i+1)+"个手机的价格是"+price);
System.out.println("正在调用第"+(i+1)+"个手机的打电话功能");
p.get(i).call();
System.out.println("正在调用第"+(i+1)+"个手机的发短信功能");
p.get(i).sendMessage();
}
}
//添加数据到集合
public static void addPhone(ArrayList<Phone> p) {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
Phone phone = new Phone();
System.out.println("请输入手机品牌");
phone.setBrand(sc.next());
System.out.println("请输入手机颜色");
phone.setColour(sc.next());
System.out.println("请输入手机价格");
phone.setPrice(sc.nextDouble());
p.add(phone);
}
}
}