3、封装
概述:
隐藏对象的属性的实现细节,仅对外提供公共访问方式
案例:
使用这个案例中 发现了一个问题,通过成员变量可以赋值一些非法的数据。
赋值前应先进行判断。判断在哪里做比较合适呢?
判断应该定义在student类中,而我们在成员变量的位置不能判断。因为做数据校验,必须要依靠逻辑语句。逻辑语句应该定义在方法中。最终决定在student类中提供一个方法校验。
public void setAge(int a) {
if (a < 0 || age > 120) {
System.out.println("你给的年龄有问题");
} else {
age = a;
}
}
我们给出了方法进行校验,但是,它不用方法,还是直接赋值了。方法就没有起到作用。
就应该要求它必须使用方法
// 创建学生对象
Student s = new Student();
// 给成员变量赋值
s.setAge(18);
s.name = "周十七";
s.show();
s.age = -17;
s.show ();
}
怎么强制使用方法,不走成员变量?
private:关键字可以修饰成员变量和成员方法
注意:被private修饰的成员只能在本类中访问。
private int age;
public class NoNameDemo {
public static void main(String[] args) {
// 创建学生对象
Student s = new Student();
// 给成员变量赋值
s.setAge(18);
s.name = "周十七";
s.show();
s.show ();
}
}
/*
* 定义一个学生类: 成员变量:name,age 成员方法: show()
*/
class Student {
// 姓名
String name;
// 年龄
private int age;
// show()方法,显示所有成员变量值
public void show() {
System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
}
public void setAge(int a) {
if (a < 0 || age > 120) {
System.out.println("你给的年龄有问题");
} else {
age = a;
}
}
}
原则:
将不需要对外的内容都隐藏起来。
把属性隐藏,提供公共方式对其访问。
Private关键字
1、权限修饰符
2、可以修饰成员(成员变量和成员方法)
3、被其修饰的成员只在本类中才能访问
应用
1、把成员变量用private修饰
2、提供对应的getXxx(), setXxx();
public class PrivateDemo {
public static void main(String[] args) {
Demo d = new Demo();
// System.out.println(d.num); 无法调用
d.show();// 只能通过该类的方法调用
// d.method(); 同理
d.fucntion();
}
}
class Demo {
// int num = 10;
// 用private修饰
private int num = 10;
public void show() {
System.out.println(num);// 只能在本类中调用
}
private void method() { //想调用它 必须建一个public 的方法来供外界调用
System.out.println("method");
}
public void fucntion() {
method();
}
}
public class PrivateDemo {
public static void main(String[] args) {
Demo d = new Demo();
d.setAge(18);
System.out.println(d.getAge());
}
}
class Demo {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int a) {
age = a;
}
public String getName() {
return name;
}
public void setName(String n) {
name = n;
}
}
this关键字
当前类的引用。就代表当前类的对象。 谁调用这个方法,在该方法内部的this就代表谁
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {//age 传给 当前类的age
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
this内存图解
构造方法
作用:给对象的数据进行初始化
格式: 方法名与类名 相同
方法没有返回值类型
没有具体的返回值
class Demo {
public Demo(){
System.out.println("这是一个构造方法");
}
}
我们一直在使用构造方法却一直没有定义,从哪里来?
注意事项:
如果没有给出构造方法,系统将自动提供一个无参构造方法。
如果我们给出了构造方法,系统将不再提供。
注意:(如果还想使用无参构造方法,还需要自己给出)
public class PrivateDemo {
public static void main(String[] args) {
//创建对象
Demo d = new Demo();//Demo()构造方法,
}
}
给成员变量赋值:
1、setXxx()
2、构造方法
public class ConstructDemo {
public static void main(String[] args) {
Student s = new Student();
s.show();
System.out.println("-----------------------");
//创建对象二
Student s2 = new Student("周思琪");
s2.show();
}
}
class Student {
private String name;
private int age ;
public Student() {
System.out.println("这是无参构造方法");
}
public Student(int age) {
System.out.println("这是构造方法重载");
}
public Student(String name) {
System.out.println("这是带参数的构造方法");
this.name = name;
}
public void show() {
System.out.println(name+"........"+age);
}
}
成员方法的分类
根据返回值:
有明确返回值
返回void类型
根据形式参数:
无参数方法
带参数
public 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);
}
}
class Student {
public String getString() {
return "helloworld";
}
public void show() {
}
public void method(String name) {
}
public String function(String s1,String s2) {
return s1+s2;
}
}
标准手机类练习
手机类:
成员变量: brand , price, color
构成方法 :无参构造
成员方法 :getXxx() / setXxx
public 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;
}
}
public class PhoneText {
public static void main(String[] args) {
//创建对象
Phone p = new Phone();
//给成员变量赋值
p.setBrand("vivo");
p.setColor("绿色");
p.setPrice(1999);
//获取值
System.out.println(p.getBrand()+"--"+p.getColor()+"---"+p.getPrice());
}
}
练习
001定义一个类Demo,定义一个数据和方法
变量定义在哪里?
变量的范围越小越好,可以被及时回收
public class SunDemo {
public static void main(String[] args) {
//Demo d = new Demo();
//System.out.println(d.sum());
//Demo d = new Demo();
//d.a = 10;
//d.b = 20;
//System.out.println(d.sum());
}
}
//方式一参与操作数固定
/*class Demo{
public int sum() {
int a = 10;
int b =20;
int c = a+b;
return c;
}
}*/
//方式二 满足要求但是没有用面向对象思想
/*class Demo{
public int sum(int a, int b) {
return a+b;
}
}*/
//方式三 成员变量a , b 但是这个变量和这个类没有关系不应该定义为成员变量
/*class Demo {
int a;
int b;
public int sum(){
return a+b;
}
}*/
002定义一个长方形类,定义周长和面积的方法
长方形的类:
成员变量:
成员方法:
求周长 : (长+宽)*2
求面积: 长*宽
import java.util.Scanner;
public class SquareDemo {
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();
// 创建对象
Square s = new Square();
s.setLength(length);
s.setWidth(width);
System.out.println("长方形的周长是:"+s.getPerimeter());
System.out.println("长方形的面积是:"+s.getarea());
}
}
class Square {
// 长方形的长
private int length;
// 长方形的宽
private int width;
public Square() {
}
// 仅仅提供setXxx即可
public void setLength(int length) {
this.length = length;
}
public void setWidth(int width) {
this.width = width;
}
// 求周长
public int getPerimeter() {
return (length + width) * 2;
}
// 求面积
public int getarea() {
return (length * width);
}
}
static关键字
1、共享成员变量country
public class PersonDemo {
public static void main(String[] args) {
// 创建对象
Person p1 = new Person("周思琪", 17, "中国");
p1.show();
Person p2 = new Person("周子豪", 17);
p2.show();
Person p3 = new Person("账号一", 17);
p3.show();
}
}
class Person {
// 姓名
String name;
// 国籍
String country;
// 年龄
int age;
public Person() {
}
public Person(String name, int age) {
this.age = age;
this.name = name;
}
public Person(String name, int age, String country) {
this.age = age;
this.country = country;
this.name = name;
}
public void show() {
System.out.println("姓名" + name +" "+"年龄" + age +" "+"国籍" + country);
}
}
public class PersonDemo {
public static void main(String[] args) {
// 创建对象
Person p1 = new Person("周思琪", 17, "中国");
p1.show();
Person p2 = new Person("周子豪", 17);
p2.show();
Person p3 = new Person("账号一", 17);
p3.show();
}
}
class Person {
// 姓名
String name;
// 国籍
static String country;
// 年龄
int age;
public Person() {
}
public Person(String name, int age) {
this.age = age;
this.name = name;
}
public Person(String name, int age, String country) {
this.age = age;
this.country = country;
this.name = name;
}
public void show() {
System.out.println("姓名" + name +" "+"年龄" + age +" "+"国籍" + country);
}
}
Person p1 = new Person("周思琪", 17, "中国");
p1.show();
Person p2 = new Person("周子豪", 17);
p2.show();
Person p3 = new Person("账号一", 17);
p3.show();
p3.country = "美国";
p3.show();
p2.show();
p1.show();
}
}
static 特点
1、随着类加载而加载
2、优先对象存在
3、被所有类的对象共享
举例:咋们班的学生应该共用同一个班级编号。
什么时候使用静态:
如果某个人成员变量是被所有对象共享,那么它应该是静态的。
4、可以通过类名调用
其实它本身也可以通过对象名调用。
推荐使用类名调用。
静态修饰的内容一般称其为:与类相关的,类成员
public class asdasd {
public static void main(String[] args) {
Student s = new Student();
//非静态
System.out.println(s.num);
//静态
System.out.println(Student.num2);
}
}
class Student{
int num = 10;
static int num2 =20;
}
注意事项:
001静态方法中是没有关键字的
理解:
静态是随着类加载而加载,this是随着对象的创建而存在的。
静态比对象先存在。
002静态方法只能访问静态的成员变量和静态的成员方法。
静态方法:
成员变量:只能访问静态变量
成员方法:只能访问静态成员方法
非静态方法:
成员变量:可以是静态的,也可以是非静态的
成员方法 :都可以
静态只能访问静态,非静态可以访问一切
静态变量和成员变量区别
所属不同
静态变量 属于 类 也称类变量
成员变量 属于 对象 也称实例变量(对象变量)
内存中位置不同
静态变量存储于方法区的静态区
成员变量存储于堆内存
内存出现时间不同
静态变量随着类加载而加载,随着类消失而消失
成员变量随着对象创建而存在,随着对象消失而消失
调用不同
静态变量可以通过类名调用,也可以对象调用
成员变量只能通过对象名调用