文章目录
- 1. 啥是封装 ?
- 1.1 封装好处
- 1.2 权限修饰符
- 1.2.1 测试权限,在相同包下
- 1.2.2 测试权限,在不相同包下
- 1.3 Get()方法和Set()方法使用
- 1.4 封装并不单纯指 private
- 1.5 课堂练习:封装学生类信息
- 2. 构造函数
- 2.1 概述
- 2.2 语法结构
- 2.3 构造方法的使用
- 3. 代码块(静态代码块,构造代码块,局部代码块)
- 3.1 构造代码块
- 3.2 局部代码块
- 3.3 静态代码块
- 3.4 代码块的执行顺序
- 4. this关键字
- 4.1 概述
- 4.2 使用场景
- 4.2.1 练习:区分变量名相同
- 4.2.2 练习:构造方法调用
- 4.3 比较两个人的名字是否相同
1. 啥是封装 ?
- 上一节了解了java中重要的概念,类和对象,也就算入门了思想编程阶段了,接下来也属于的编程思想上的延伸,我们java的核心思想是面向对象操作,既然是面向对象,就要了解面向对象的三大特征也是核心思想,封装,继承,多态。。
- 那么什么是封装 ?封装是指将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来对隐藏的信息进行操作和访问。
- 可以理解为是将 属性和方法封装起来,而将属性和方法封装起来的载体就是 类。
- 列举生活中的一些例子:
- 开车, 我们只要学会开就可以,不需要了解发动机是如何驱动的。
- 电插座, 只需要知道如何使用即可,不需要直到里面电路集成原理。
1.1 封装好处
- 封装的好处: 保证了类的数据结构的完整性,使用该类,的用户不能轻易的操作数据结果,只允许操作公开的数据,就避免了对内部数据的影响,提高了程序的可维护性。
- 只能通过规定的方法去访问数据。
- 隐藏了实例细节,增加了数据安全性。
- 总结: 相当于把 功能封装进对象, 强调,对象具备了这样的功能! 将变化隔离,提高重用性、提高安全性!
1.2 权限修饰符
- 用来控制类和类的 成员变量 以及 成员方法 的方法范围。
-
default :
是没有修饰属性的时候,有默认为修饰。 只有同包类可以调用,子类不行。
修饰符 | 本类 | 同包其他类和子类 | 不同包的类或子类 |
private | 可见 | 看不可 | 看不见 |
protected | 可见 | 可见 | 看不见 |
default(默认) | 可见 | 可以(子类看不见) | 看不见 |
public | 可见 | 可见 | 可见 |
1.2.1 测试权限,在相同包下
- 在相同的包下,
在这里插入代码片
package com.oop.var;
/**
* 人类的属性
* 实际开发中属性都是私有的private的。
*/
public class VarTest {
private String name; // 姓名
protected int age; // 年龄
char sex; // 性别 '男',‘女’
public String address; //地址
/**
* 测试方法 : 吃 喝 玩 乐
*/
private void eat(){
System.out.println("方法: private eat输出");
}
void drink(){
System.out.println("方法: 默认 drink输出");
}
public void play(){
System.out.println("方法: public play输出");
}
protected void happy(){
System.out.println("方法:protected 输出 ");
}
}
- 相同包的测试类。
package com.oop.var;
public class VarTest01 {
public static void main(String[] args) {
//测试 同包 不同类
VarTest vt3 = new VarTest();
//方法 测试
vt3.play(); //玩方法public
vt3.drink(); // 默认
vt3.happy(); // protected 修饰
//属性 测试
System.out.println(vt3.age);
System.out.println(vt3.sex); // 默认输出为 空字符
System.out.println(vt3.address);
}
}
- 输出结果:
方法: public play输出
方法: 默认 drink输出
方法:protected 输出
0
null
1.2.2 测试权限,在不相同包下
- 在不相同的包下测试权限范围。 上面接
VarTest
类。
package com.oop.var2;
import com.oop.var.VarTest;
/**
* 不同包 测试权限修饰
* public private protected 默认default
*/
public class VarTest2 {
public static void main(String[] args) {
// 使用类的对象 就需要实例化 new
VarTest vt2 = new VarTest();
//不同包里面只有public可以看见
System.out.println(vt2.address);
/*方法测试*/
vt2.play(); // 直接输出方法,因为没有返回值
}
}
- 输出结果:
null
方法: public play输出
1.3 Get()方法和Set()方法使用
- 信息时代用户信息很重要,私有变量无法访问,关键字
private
去私有化变量,如果无法访问属性怎么办? 只能通过公共访问方法; - 下面封装用户的信息。
/**
* 用户类
*/
public class User {
// 用户属性
private String userName; //private 私有用户
private int age; // private 私有年龄
//对外提供方法的方法 get方法
public String getUserName(){
return userName;
}
// 对外提供修改方法 set方法
public void setUserName(String name){
userName=name; //相当于 this.name = name;
}
// 年龄对外提供
public void setAge(int age){
// 进行封装内部处理 ,来处理负数的问题
if (0<=age||age>=100){
userAge =age;
}else{
System.out.println("输入错误,请从新输入");
}
}
public int getUserAge(){
return userAge;
}
}
- 测试类:
- 只有对外提供方法,才能访问私有变量;
public class UserTest {
public static void main(String[] args) {
User u = new User(); //创建对象
String userName = u.getUserName();
System.out.println(userName);
u.setUserName("周杰伦");
System.out.println(u.getUserName());
//如果设置 int 为负数?
u.setAge(-20); // 年龄为负数?? 怎么办?
System.out.println(u.getUserAge()); // 输入0 是因为默认值
}
}
输出结果:
null
周杰伦
输入错误,请从新输入
0 // 在调用了一次 getUserAge() 默认值
1.4 封装并不单纯指 private
- 封装 并不是单纯指使用权限修饰符修饰属性和方法, 更广义的意思指将某些复杂的功能集成起来形成模块化,让使用者调用该模块即可。
- 其作用增加了代码的复用性。
- 如案例:数组之前学过的根据元素查询该元素下的索引。
public class ArrayDemo {
public static void main(String[] args) {
//1.定义数组
String[] arr = {"张三","李四","王五","赵六"};
System.out.println("请输出查询元素: ");
String arr2 = new Scanner(System.in).next();//匿名对象使用。
//2.业务逻辑处理,如何通过元素获取下标。
for (int i = 0; i <arr.length ; i++) {
//2.1 判断
if (arr2.equals(arr[i])){
System.out.println(i);
break;//如果查询出,跳出即可
}
}
}
}
- 这样的代码,没有将核心代码进行封装,造成了复用率低,使用者如果要查询索引,都得写一遍这个代码。并且核心代码也暴露了在外面。所以 广义上得封装,就是将核心代码封装起来对外提供访问方法即可。
public class ArrayDemo {
public static void main(String[] args) {
String[] arr = {"张三","李四","王五","赵六"};
int resault = new Utils().seach_Index(arr, "王五"); //通过这一句话就可以调用。
System.out.println(resault);
}
}
//1.将方法进行封装。
class Utils{
/**
*
* @param o 数组名
* @param o1 传入查询元素
* @return int 类型 -1没有查询到。
*/
public int seach_Index(Object[] o, Object o1 ){
for (int i = 0; i <o.length ; i++) {
if (o1.equals(o[i])){
return i;
}
}
return -1; //返回-1就是没有
}
}
1.5 课堂练习:封装学生类信息
- 通过上述学习的封装思想,将学生类必要的属性封装起来,方便创建对象,调用对象使用。oop思想。
- 使用get()和set()方法对外提供访问。
public class Students {
//1. 私有化属性
private String name;//姓名
private int age;//年龄
private String adress; //地址
//2.对外提供访问方法get和set方法
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 getAdress() {
return adress;
}
public void setAdress(String adress) {
this.adress = adress;
}
//3. 封装自己独特的方法例如 介绍自己
public void introduce(){
System.out.println("我的名字叫"+name+",年龄 "+age+",家在"+adress);
}
}
- 测试类,同包下。
public class Student_Test {
public static void main(String[] args) {
//1.创建对象1
Students s = new Students();
int age = s.getAge();
System.out.println(age); //返回值是0,因为什么?
//2.给属性赋值 通过set方法
s.setName("张三");
s.setAge(18);
s.setAdress("北京");
s.introduce();
//2.创建对象2
Students s2 = new Students();
s2.setName("李四");
s2.setAge(30);
s2.setAdress("上海");
s2.introduce();
}
}
2. 构造函数
2.1 概述
- 构造方法和它所在类的名字相同,注意:不用定义返回值类型,即不用
void
修饰。 - 当一个对象被创建时候,就会 自动调用默认的空参构造方法。
- 不管你是否自定义构造方法,所有的类都有默认的 空参构造方法,因为 Java 自动提 供了一个默认构造方法, 默认构造方法的访问修饰符和类的访问修饰符相同 (类为 public,构造函数也为 public;类改为 protected,构造函数也改为 protected)。
- 一旦你定义了自己的构造方法(如含参数),默认的空参构造方法就会失效。
- 构造方法的作用:即给重要属性赋初始值。
2.2 语法结构
- 构造函数可以有参数,也可以没有参数。
- 默认的是空参数构造方法。
- 构造方法可以重载 (方法名相同,参数不同)。
//修饰符 如果没有就是默认 default
修饰符 方法名(参数){ //方法名必须与类名一致。参数可由可无
初始化;
}
2.3 构造方法的使用
- 构造方法的作用是什么 ? 什么时候调用构造方法?
- 创建对象时,即
new
会调用默认的空参构造方法,进行初始化赋值。
public class Student {
private String name;
private int age;
/**
* java提供了一个默认的构造方法;
*/
//1.空参数构造
public Student() {
//自己定义
System.out.println("我是构造方法");
}
//2.一个参数构造
public Student(String name) {
//同时给可以赋值
//age=10; 也可以给属性初始化值
this.name = name;
}
//3.多参数构造
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//普通方法,输出属性
public void introduce(){
System.out.println("name="+name+" , age= "+age);
}
//main 方法程序入口
public static void main(String[] args) {
//1,调用的是无参数构造方法
Student s1 = new Student();
s1.introduce();
//2.调用的是含参数构造方法
Student s2 = new Student("张三", 30);
s2.introduce();
//3.调用的是单个参数构造方法
new Student("李四").introduce();
}
}
- 输出结果:
我是构造方法
name=null , age= 0
name=张三 , age= 30
name=李四 , age= 10
3. 代码块(静态代码块,构造代码块,局部代码块)
- 啥叫代码块? 就是用
{ }
括起来的代码块;
- 根据位置不同,分构造代码块 和 局部代码块。
- 根据修饰符不同,如果被
static
关键字修饰的代码块,叫静态代码块,随着类的加载而加载。
// Person{} 就是一个代码块 ,即{}就是代码块
class Person{
public static void main(String[] args){
}
}
3.1 构造代码块
- 构造代码块 。
- 位置: 在 类的内部,方法外部,的代码块。
- 作用: 通常用于抽取 构造方法中的共性代码。
- 加载顺序:每次调用构造方法前都会调用构造代码块,优先于构造方法加载。
- 构造代码块案例。
public class Person {
private String name; //名字
private String country; //国家
private String city; // 城市
//4. 构造代码块,
{
country="中国";//初始化成员变量
System.out.println("语言:汉语");
}
//5.set和get方法
public void setCountry(String country) {
this.country = country;
}
public String getCountry() {
return country;
}
//1.空参构造方法
public Person() {
System.out.println("语言:汉语");
}
//2.带多个参数构造方法
public Person(String name, String country, String city) {
this.name = name;
this.country = country;
this.city = city;
System.out.println("语言:汉语");
}
//3.带一个参数的构造方法
public Person(String country) {
this.country = country;
System.out.println("语言:汉语");
}
public static void main(String[] args) {
Person p = new Person();
//new Person("中国");
//没有调用set()方法进行赋值。会输出什么?
System.out.println(p.country);//输出中国,由构造代码块提前赋值。
p.setCountry("China");
System.out.println(p.getCountry());//输出China,有set方法更改了值。
}
}
- 输出结果:
语言:汉语
语言:汉语
中国
China
3.2 局部代码块
- 局部代码块。
- 位置: 在方法里面的代码块。
- 作用: 通常用于控制变量的作用范围,出了括号就失效。
- 加载顺序: 构造代码块是最优先的,然后局部代码块当方法调用时才会执行。
- 局部代码块。
public class Person2 {
private int age;
//1.普通方法
public void init(){
{
int age=10;//优先于加载局部代码块的值age
System.out.println("我是局部代码块 "+age);
}
System.out.println(age);// 成员变量的age
}
public static void main(String[] args) {
Person2 p = new Person2();
p.init();
}
}
- 输出结果:
我是局部代码块 10
0
3.3 静态代码块
- 被关键字
static
修饰的代码块,就是静态代码块。
- 位置: 在类里,方法外。
- 作用: 一般用于加载项目驱动(加载配置文件),或者项目初始化。
- 加载顺序: 优先于类的加载而加载,只加载一次。
- 静态代码块。
public class Person3 {
//private String IP;//ip地址
private static String hostName;// 主机地址
//1.空参构造方法
public Person2() {
System.out.println("我是构造方法");
}
//2.作用,在类的加载之前加载,提前加载配置文件。
static {
hostName ="192.168.1.1";//静态代码块只能给静态属性赋值;
System.out.println("我是静态代码块");
}
public void conn(){
String ip ="192.168.1.1";//数据接口
if (ip.equals(hostName)){
System.out.println("连接成功");
}else {
System.out.println("连接失败");
}
}
public static void main(String[] args) {
new Person3().conn();
System.out.println("-----------");
new Person3();//第二次就不会调用,只加载一次。
}
}
- 输出结果:
我是静态代码块
我是构造方法
连接成功
-----------
我是构造方法
3.4 代码块的执行顺序
- 静态代码块 > 构造代码块> 构造方法>局部代码块
public class Person4 {
public void init(){
{
System.out.println("局部代码块");
}
}
{
System.out.println("构造代码块");
}
static{
System.out.println("静态代码块");
}
public Person4(){
System.out.println("构造方法");
}
public static void main(String[] args) {
new Person4();
//1.局部代码块只有在调用方法时才会执行
// new Person4().init();
}
}
- 输出结果:
静态代码块
构造代码块
构造方法
4. this关键字
4.1 概述
- java里面
this
是指 本身 的意思,当前类,本类对象的一个引用对象。 - 形参与成员变量重名时,可以用
this
关键字来区分?
- 是不是很熟悉这句话?哪见过?
set() 和 get()
方法。
- 只能在构造函数中使用。
-
this();
必须放在第一行。
4.2 使用场景
4.2.1 练习:区分变量名相同
- 区分同名参数,
this
相当于本类调用。
public class Test_this {
private String name;
//构造方法
public Test_this(){
System.out.println("空参构造方法");
}
//1.类似于 set赋值方法。
public void setName1(String name1){
name = name1; // 给成员变量赋值
}
public void setName(String name) {
//形式参数名称和成员变量名称相同时,使用this区别,相当于 Test_this.name=name;
this.name = name;
}
public String getName() {
return name;
}
//2. 普通方法
public void info(){
System.out.println(this.getName());//相当于 Test_this.getName();
}
public static void main(String[] args) {
new Test_this();
Test_this t = new Test_this();
t.setName1("张三");
//打印输出name值
System.out.println(t.getName());
t.info();
}
}
- 输出结果:
空参构造方法
空参构造方法
张三
张三
4.2.2 练习:构造方法调用
-
this(参数)
,相当于调用类中的构造方法, 但是必须放在第一行。 - 并且在类中,只能出现一个
this()
;
- 不能同时在两个构造方法中使用
this();
public class Test_this {
private String name;
//1.空参构造方法
public Test_this(){
this("张三"); //只能出现一个this()引用构造函数。
System.out.println("空参构造方法");
// this(""); //必须放在首行。
}
//2.含参数构造方法
public Test_this(String name) {
//this(); //只能出现一个this();引用的构造函数
this.name = name;
System.out.println("含参数构造函数");
}
public String getName() {
return name;
}
public static void main(String[] args) {
String name = new Test_this().getName();//通过调用含参构造方法赋值
System.out.println(name);
}
}
- 输出结果:
含参数构造函数
空参构造方法
张三
4.3 比较两个人的名字是否相同
- 创建两个对象比较它们之间的年龄是否相等。
- 使用
this
关键字。
public class Test_this {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//2.当使用this之后的写法
public Boolean compare2(Test_this t){
return this.getAge() == t.getAge();//不同包下可以方法
//return this.age == t.age; //本类方法私有。
}
public static void main(String[] args) {
Test_this t = new Test_this();
t.setAge(18);
Test_this t2 = new Test_this();
t2.setAge(18);
Boolean compare = t.compare2(t2);
System.out.println(compare);
}
}