学习JavaEE的日子 day13 封装 static private this

Day13

1. private – 私有化

理解:private是访问修饰符的一种,访问修饰符规定了访问权限.

作用:

1.private修饰属性:该属性只能在类的内部使用

2.private修饰方法:该方法只能在类的内部使用

应用场景:不让让外界访问的属性和方法就用private修饰

public class A {

	private String str = "好好学习";
	
	private void method01(){
		System.out.println("aaabbbccc -- " + str);
	}
	
	public void method02(){
		method01();
	}
}
public class Test01 {
	public static void main(String[] args) {
		
		A a = new A();
		
		a.method02();	
	}
}

2. 封装

面向对象三大特征之一: 封装,继承,多态

理解:不能直接操作属性,可以添加get/set方法

*对象代表什么,就得封装对应的数据,并提供数据对应的行为*

步骤:

1.私有化属性: 成员变量使用private

2.添加get-获取/set-设置方法

好处:外界不能直接操作属性(有风险),通过get/set方法操作属性,可以在方法内添加额外的功能

将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问

思考题:操作属性有什么功能?

1.设置属性 – set

2.获取属性 – get

set 存 get 取 先存后取,在set中做判断等操作

需求:模拟银行用户操作余额的功能

分析:

操作余额(存钱、取钱、查看)

import java.time.LocalDateTime;

public class User {

	String username;
	String password;
	String name;
	private double surplus;//余额
	
	public User() {
	}

	public User(String username, String password, String name, double surplus) {
		this.username = username;
		this.password = password;
		this.name = name;
		this.surplus = surplus;
	}
	
	//设置余额
	public void setSurplus(double surplus){
		//额外的功能
		double num = (surplus - this.surplus);
		System.out.println(LocalDateTime.now() + " -- " + this.name + "用户操作了金额:" + ((num>0)?"+":"") + num); //显示当前时间
		
		//设置属性
		this.surplus = surplus;
	}
	
	//获取余额
	public double getSurplus(){
		//额外的功能
		System.out.println(LocalDateTime.now() + " -- " + this.name + "用户获取了金额");
		
		//返回余额
		return surplus;
	}
}
public class Test01 {
	public static void main(String[] args) {
		
		User user = new User("1445584980", "123123", "小彭",  2000);
		
		//存钱
		//user.surplus = user.surplus+200;
		user.setSurplus(user.getSurplus() + 200);
		
		//取钱
		//user.surplus = user.surplus-1800;
		user.setSurplus(user.getSurplus() -1800);
		
		//查看
		//System.out.println(user.surplus);//400.0
		System.out.println(user.getSurplus());//400.0
	}
}

运行结果:

在这里插入图片描述

3. this

概念:表示本对象

理解:哪个对象调用该方法,该方法里的this就表示该对象

作用:

1.this.属性:调用本对象的成员属性

2.this.方法:调用本对象的成员方法

3.this():在构造方法的第一句调用本类另外的构造方法

问题: 成员变量何时在内存中存在? 静态变量何时在内存中存在?

成员变量在创建对象时。静态变量在类创建时就有

成员变量会在对象被创建时分配内存并存在于对象的内存空间中;静态变量在类加载时被初始化,此时就会在内存中分配空间

import java.time.LocalDateTime;

public class User {
	private String username;
	private String password;
	private String name;
	private double surplus;//余额
	
	public User() {
		//在当前构造方法中调用另一个构造方法
		this("默认账号", "默认密码", "亚当",  0.0);
	}
	
	public User(String username, String name, String phone, char sex, double surplus) {
		//在当前构造方法中调用另一个构造方法
		this(username,"000000", name, phone, sex, surplus);
	}

	public User(String username, String password, String name, double surplus) {
		this.username = username;
		this.password = password;
		this.name = name;
		this.surplus = surplus;
	}
	
	//设置余额
	public void setSurplus(double surplus){
		//额外的功能
		double num = (surplus - this.surplus);
		System.out.println(LocalDateTime.now() + " -- " + this.name + "用户操作了金额:" + ((num>0)?"+":"") + num);
		
		//设置属性
		this.surplus = surplus;
	}
	
	//获取余额
	public double getSurplus(){
		//额外的功能
		System.out.println(LocalDateTime.now() + " -- " + this.name + "用户获取了金额");
		
		//返回余额
		return surplus;
	}
	
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	/**
	 * 转账
	 * @param username 对方的账号
	 * @param money 转账的金额
	 */
	public void transferAccounts(String username,double money){
		
		//获取本对象的余额,判断是否比转账的金额更多
		if(this.getSurplus() > money){
			
			//将当前用户的余额的money部分转给对方账号
			//this.setSurplus(this.getSurplus()-money);
			setSurplus(getSurplus()-money);
			System.out.println("已经给" + username + "转账成功");
			
		}else{
			System.out.println("余额不足");
		}
	}
}
public class Test01 {
	public static void main(String[] args) {
		
//		User user = new User("1445584980", "123123", "小彭", 2000);
//		user.transferAccounts("12345678999", 800);
	}
}

4. static修饰属性

概念:

1.成员属性:每个对象独享一份

2.静态属性:每个对象共享一份

3.静态属性何时创建?

使用到类,JVM会判断方法区中是否有该类的class文件,如果没有,就把该类的class文件加载到方法区

JVM会扫描该类的所有属性,并把属性添加到静态区中(1.开辟空间 2.赋系统的默认值)

4.静态属性何时销毁?

项目结束时,静态属性才会被销毁,所以静态属性的生命周期很长,项目中使用时需警慎

5.静态属性的应用场景?
该类所有的对象需要共享的属性,就可以设置为静态

注意:静态属性属于类的属性,直接使用类名调用。使用对象调用会出现警告

静态属性比成员属性更早的在内存中存在

public class A {
	
	//成员属性
	String str1;
	
	//静态属性
	static String str2;
}
public class Test01 {
	public static void main(String[] args) {
		
		A a1 = new A();
		A a2 = new A();
		
		a1.str1 = "aaa";
		a2.str1 = "bbb";
		System.out.println(a1.str1);//aaa
		System.out.println(a2.str1);//bbb
		
		//注意:静态属性属于类的属性,直接使用类名调用。使用对象调用会出现警告
//		a1.str2 = "xxx";
//		a2.str2 = "yyy";
//		System.out.println(a1.str2);//yyy
//		System.out.println(a2.str2);//yyy
		
		A.str2 = "xxx";
		A.str2 = "yyy";
		System.out.println(A.str2);//yyy
		System.out.println(A.str2);//yyy
	}
}

注意:A.str2不是xxx,而是yyy

由于静态属性存在静态区,其属性不允许重复,不同调用赋值会覆盖掉

static修饰属性内存图:

在这里插入图片描述

5.static修饰方法

成员方法 vs 静态方法 应用场景

成员方法:必须使用对象调用,也就是说调用成员方法之前必须创建对象(开辟空间)

静态方法:属于类的方法,直接使用类名调用,纯功能的方法就可以设计成静态方法(工具类),比如MyArrays

需求:模仿Java的MyArrays,编写自己的MyMyArrays

目的:

1.掌握工具类的概念

2.回顾之前的知识点

3.理解文档注释的作用

/**
 * 自己编写的数组工具类
 * @author 小彭
 * @version 1.0
 */
public class MyArrays {

	/**
	 * 数组的排序
	 * @param a 目标数组
	 */
	public static void sort(int[] a){
		for (int i = 0; i < a.length-1; i++) {
			for (int j = 0; j < a.length-1-i; j++) {
				if(a[j] > a[j+1]){
					int temp = a[j];
					a[j] = a[j+1];
					a[j+1] = temp;
				}
			}
		}
	}
	
	/**
	 * 数组的查找,必须先排序,在查找
	 * @param a 目标数组
	 * @param key 需要查找的元素
	 * @return 如果搜索的元素包含在数组中就返回元素的下标; 否则,返回(-插入点-1)
	 */
	public static int binarySearch(int[] a,int key){
		int start = 0;
		int end = a.length-1;
		while(start <= end){
			int mid = (start+end)/2;
			if(key < a[mid]){
				end = mid-1;
			}else if(key > a[mid]){
				start = mid+1;
			}else{
				return mid;
			}
		}
		return -start-1;
	}
	
	/**
	 * 拷贝数组
	 * @param original 目标数组
	 * @param newLength 新数组的长度
	 * @return 新数组
	 */
	public static int[] copyOf(int[] original, int newLength){
		
		int copyLength = original.length;
		if(copyLength > newLength){
			copyLength = newLength;
		}
		
		int[] newArr = new int[newLength];
		
		for (int i = 0; i < copyLength; i++) {
			newArr[i] = original[i];
		}
		return newArr;
	}
	
	/**
	 * 拷贝区间数组
	 * @param original 目标数组
	 * @param from 开始下标-包含
	 * @param to 结束下标 - 排他
	 * @return 新数组
	 */
	public static int[] copyOfRange(int[] original, int from, int to){
		
		int newLength = to-from;
		int[] newArr = new int[newLength];
		
		int index = 0;
		for (int i = from; i < to; i++) {
			newArr[index++] = original[i];
		}
		return newArr;
	}
	
	/**
	 * 替换全部元素
	 * @param a 目标数组
	 * @param val 替换的值
	 */
	public static void fill(int[] a, int val){
		fill(a, 0, a.length, val);
	}
	
	/**
	 * 替换区间元素
	 * @param a 目标数组
	 * @param fromIndex 开始下标 - 包含
	 * @param toIndex 结束下标 - 排他
	 * @param val 替换的值
	 */
	public static void fill(int[] a, int fromIndex, int toIndex, int val){
		for (int i = fromIndex; i < toIndex; i++) {
			a[i] = val;
		}
	}
	
	/**
	 * 将数组转换为字符串
	 * @param a 目标数组
	 * @return 转换后的字符串
	 */
	public static String toString(int[] a){
		String str = "[";
		for (int element : a) {
			if(str.length() != 1){
				str += ",";
			}
			str += element;
		}
		str += "]";
		
		return str;
	}
	
}
import com.qf.array.MyArrays;

public class Test01 {
public static void main(String[] args) {
	int[] arr = {18,32,81,63,20,9};
	
	//排序 - [9, 18, 20, 32, 63, 81]
	MyArrays.sort(arr);
	
	//查找(底层还用二分法去查找元素,所以必须先排序,再查找!)
	//返回值规则:如果搜索的元素包含在数组中就返回元素的下标; 否则,返回(-插入点-1)
	int index = MyArrays.binarySearch(arr, 28);
	System.out.println("查找元素的下标为:" + index);
	
	//拷贝数组(目标数组,新的长度)- [9, 18, 20, 32, 63, 81, 0, 0, 0, 0]
	int[] copyOf = MyArrays.copyOf(arr, 10);
	
	//拷贝区间数组(目标数组,开始下标-包含,结束下标-排他)- [18, 20, 32, 63, 81, 0, 0]
	int[] copyOfRange = MyArrays.copyOfRange(copyOf, 1, 8);
	
	//替换元素 - [666, 666, 666, 666, 666, 666, 666]
	MyArrays.fill(copyOfRange, 666);
	
	//替换区间元素(目标数组,开始下标-包含,结束下标-排他,替换的值) - [666, 666, 888, 888, 888, 666, 666]
	MyArrays.fill(copyOfRange, 2, 5, 888);
	
	//将数组转换为字符串
	String str = MyArrays.toString(copyOfRange);
	System.out.println(str);
	
}

6. 静态代码块

静态代码块是类加载到方法区时才会被调用,该代码块只能初始化静态变量

代码块是创建对象时优先于构造方法调用,该代码块可以初始化成员变量和静态变量()

构造方法是创建对象时调用,该方法可以初始化成员变量和静态变量

经验:

1.创建对象时,在构造方法中初始化数据

2.项目中可以在静态代码块中初始化静态属性

public class A {

	String str1;//成员属性
	static String str2;//静态属性
	
	//静态代码块:class文件加载到方法区时调用
	//作用:操作静态属性,不能操作成员属性
	static{
		A.str2 = "eee";//底层实现:A.str2 = "eee";
		System.out.println("静态代码块 --" + A.str2);
	}
	
	//代码块:创建对象时优先于构造方法调用
	//作用:操作成员属性和静态属性
	{
		str1 = "ccc";//底层实现:this.str1 = "ccc";
		str2 = "ddd";//底层实现:A.str2 = "ddd";
		System.out.println("代码块-- " + str1 + " -- " + str2);
	}
	
	//构造方法:创建对象时调用构造方法
	//作用:操作成员属性和静态属性
	public A() {
		str1 = "aaa";//底层实现:this.str1 = "aaa";
		str2 = "bbb";//底层实现:A.str2 = "bbb";
		System.out.println("构造方法 -- " + str1 + " -- " + str2);
	}	
}
public class Test01 {
	public static void main(String[] args) {	
	A a1 = new A();
	A a2 = new A();
  }
}

思考题:什么算使用到该类了?

1.新建一个类的对象

2.调用该类的静态属性

3.调用该类的静态方法

4.Class.forName(“java.lang.String”)

7.分包

基本作用:防止了类的重名问题

项目作用:项目中有众多的类,把相同功能的类放在同一个包中,方便管理

工具类:com.dream.util/tool

实体类:com.dream.vo/bean/entity/bto/pojo

数据库类:com.dream.dao/mapper

包名的命名规范

路径名.路径名.xxx.xxx

例如:com.pcb.Work

8. 导出jar包

1.项目右键,选择 Export,然后选择java下的 JAR file (java项目选择JAR,web项目上线选择WAR)

在这里插入图片描述

2.选择路径(桌面)

在这里插入图片描述

3.桌面上出现JAR图标

在这里插入图片描述

9. 导入JAR包

1.项目右键选择Folder,新建一个文件夹,名为lib

在这里插入图片描述

2.将需要的JAR包放在lib文件夹中

在这里插入图片描述

3.右键选择Build path ,建立链接

在这里插入图片描述

10.导出API

1.项目右键选择Export ,选择Javadoc

在这里插入图片描述

2.选择jdk中的javadoc.exe,然后选择存放路径桌面(注意:生成的是一个一个页面,所有在桌面后面加一个UtilsAPI文件夹)

在这里插入图片描述

3.等待生成

在这里插入图片描述

在这里插入图片描述

4.怎么找–打开文件夹,选择index.html,就可以了

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

static存在的主要意义

static的主要意义是在于创建独立于具体对象的变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

static的独特之处
1、被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。 就是说,一个类的静态成员,它是属于大伙的【大伙指的是这个类的多个对象实例,我们都知道一个类可以创建多个实例!】,所有的类对象共享的,不像成员变量是自个的【自个指的是这个类的单个实例对象】
2、在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。
3、static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!
4、被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。

static注意事项
1.静态只能访问静态。
2.非静态既可以访问非静态的,也可以访问静态的

简答题

1.面向对象特征
封装:一是为了代码的高内聚低耦合,再是为了数据的安全性
继承:子类可以继承父类的属性和方法,并可以扩展自己的属性方法
多态:首先要有继承,重写,然后父类的引用可以指向多个不同子类对象。多态分为编译时多态和运行时多态,方法重载就是编译时多态的体现,方法重写就是运行时多态的体现。

12. 总结

1.private关键字 – 私有化
修饰属性:属性不能被外界访问
修饰方法:方法不能被外界访问

2.封装
步骤:
1.私有化属性
2.get/set方法

注意:理解封装的概念

3.面相对象版本的五子棋
a.私有化属性的业务场景
b.私有化方法的业务场景
c.状态码 – play方法的返回值

4.static
a.修饰属性
b.修饰方法(注重MyArrays,导出Jar包、导入Jar包、导出API)
c.静态代码块

  • 33
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A 北枝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值