学习JavaEE的日子 day13 封装 static private this 类加载机制

news2025/1/17 18:10:04

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():在构造方法的第一句调用本类另外的构造方法

this修饰的变量用于指代成员变量,其主要作用是(区分局部变量和成员变量的重名问题)

​ 方法的形参如果与成员变量同名,不带this修饰的变量指的是形参,而不是成员变量

​ 方法的形参没有与成员变量同名,不带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,就可以了

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

11.类加载机制面试题 – 深入类加载机制

类加载机制内存图:

在这里插入图片描述

初识类加载过程

使用某个类时,如果该类的class文件没有加载到内存时,则系统会通过以下三个步骤来对该类进行初始化

1.类的加载(Load) → 2.类的连接(Link) → 3.类的初始化(Initialize)

  • 类的加载(Load):将类的class文件读入内存,并为之创建一个java.lang.Class的对象,此过程由类加载器(ClassLoader )完成

  • 类的连接(Link):将类中的数据加载到各个内存区域中

  • 类的初始化(Initialize):JVM负责对类进行初始化

深入类加载过程

类的完整生命周期 :加载、连接(验证、准备、解析)、初始化、使用、卸载

  1. 加载

    1. 通过一个类的全限定名来获取其定义的二进制字节流

    2. 将这个字节流所代表的的静态存储结构转化为方法区的运行时数据结构

    3. 在堆中生成一个代表这个类的Class对象,作为方法区中这些数据的访问入口

    4. 注意: 相对于类加载过程的其他阶段而言,加载阶段是可控性最强的阶段,因为程序员可以使用系统的类加载器加载,还可以使用自己的类加载器加载,在这里我们只需要知道类加载器的作用就是上面虚拟机需要完成的三件事

  2. 连接

    1. 验证

      1. 文件格式的验证:验证.class文件字节流是否符合class文件的格式的规范,并且能够被当前版本的虚拟机处理

      2. 元数据验证:主要是对字节码描述的信息进行语义分析,以保证其描述的信息符合java语言规范的要求,比如说验证这个类是不是有父类,类中的字段方法是不是和父类冲突等等。

      3. 字节码验证:这是整个验证过程最复杂的阶段,主要是通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。在元数据验证阶段对数据类型做出验证后,这个阶段主要对类的方法做出分析,保证类的方法在运行时不会做出威胁虚拟机安全的事。

      4. 符号引用验证:它是验证的最后一个阶段,发生在虚拟机将符号引用转化为直接引用的时候。主要是对类自身以外 (常量池中的各种符号引用) 的信息进行校验。目的是确保解析动作能够完成。

      5. 注意: 对整个类加载机制而言,验证阶段是一个很重要但是非必需的阶段,如果我们的代码能够确保没有问题,那么我们就没有必要去验证,毕竟验证需要花费一定的的时间。当然我们可以使用

        -Xverfty:none来关闭大部分的验证。

    2. 准备 - 重要

      准备阶段主要为类变量(static)分配内存并设置初始值。这些内存都在方法区分配。在这个阶段我们只需要注意两点就好了,类变量和初始值两个关键词:

      1. 类变量(static):会分配内存,但不会对应的分配值,其次实例变量不会分配空间,因为实例变量主要随着对象的实例化一块分配到java堆内存中

      2. 初始值:这里的初始值指的是数据类型默认值,而不是代码中被显示赋予的值

        比如1:public static int value = 1;

        在这里准备阶段过后的value值为0,而不是1赋值为1的动作在初始化阶段

        比如2:public static final int value = 1;

        同时被final和static修饰准备阶段之后就是1了,因为static final在编译器就将结果放入调用它的类的常量池中

    3. 解析

      解析阶段主要是虚拟机将常量池中的符号引用转化为直接引用的过程

      1. 符号引用:以一组符号来描述所引用的目标,可以是任何形式的字面量,只要是能无歧义的定位到目标就好,就好比在班级中,老师可以用张三来代表你,也可以用你的学号来代表你,但无论任何方式这些都只是一个代号(符号),这个代号指向你(符号引用)
      2. 直接引用:直接引用是可以指向目标的指针、相对偏移量或者是一个能直接或间接定位到目标的句柄。和虚拟机实现的内存有关,不同的虚拟机直接引用一般不同
      3. 补充: 解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行
    4. 初始化

      这是类加载机制的最后一步,在这个阶段,java程序代码才开始真正执行。在准备阶段已经为类变量赋过一次值。在初始化阶端,程序员可以根据自己的需求来赋值了。一句话描述这个阶段就是执行类构造器clinit()方法的过程。

      在初始化阶段,主要为类的静态(stitic)变量赋予正确的初始值,JVM负责对类进行初始化,主要对类变量(stitic)进行初始化。在Java中对类变量进行初始值设定有两种方式:

      1. 声明类变量是指定初始值
      2. 使用静态代码块为类变量指定初始值

      补充:clinit() 方法具有以下特点:

      1. 由编译器自动收集类中所有类变量(static)的赋值动作和静态语句块(static{} 块)中的语句合并产生的,编译器收集的顺序由语句在源文件中出现的顺序决定。特别注意的是,静态语句块只能访问到定义在它之前的类变量,定义在它之后的类变量只能赋值,不能访问。例如以下代码
      class Test {
      	static {
      		i = 0;                // 给变量赋值可以正常编译通过
      		System.out.print(i);  // 这句编译器会报错,提示“非法向前引用”
      	}
      	static int i = 1;
      }
      
      1. 与类的构造函数(或者说实例构造器 init())不同,不需要显式的调用父类的构造器。虚拟机会自动保证在子类的 clinit() 方法运行之前,父类的 clinit() 方法已经执行结束。因此虚拟机中第一个执行 clinit() 方法的类肯定为 java.lang.Object。由于父类的 clinit() 方法先执行,也就意味着父类中定义的静态语句块要优于子类的变量赋值操作。例如以下代码:
      public class Test {
      	public static void main(String[] args) {
      	     System.out.println(Son.B);//输出结果是父类中的静态变量A的值,也就是2
      	}
      }
      class Father{
          public static int A = 1;
          static {
          	System.out.println("a");
              A = 2;
          }
      }
      class son extends Father {
          public static int B = A;
          
      }
      
      1. clinit() 方法对于类或接口不是必须的,如果一个类中不包含静态语句块,也没有对类变量的赋值操作,编译器可以不为该类生成 clinit() 方法。

      2. 接口中不可以使用静态语句块,但仍然有类变量初始化的赋值操作,因此接口与类一样都会生成 clinit() 方法。但接口与类不同的是,执行接口的 () 方法不需要先执行父接口的 clinit() 方法。只有当父接口中定义的变量使用时,父接口才会初始化。另外,接口的实现类在初始化时也一样不会执行接口的 clinit() 方法。

      3. 虚拟机会保证一个类的 clinit() 方法在多线程环境下被正确的加锁和同步,如果多个线程同时初始化一个类,只会有一个线程执行这个类的 clinit() 方法,其它线程都会阻塞等待,直到活动线程执行 clinit() 方法完毕。如果在一个类的 clinit() 方法中有耗时的操作,就可能造成多个线程阻塞,在实际过程中此种阻塞很隐蔽。

      4. JVM初始化步骤:

        1. 假如这个类还没有被加载和连接,则程序先加载并连接该类
          2. 假如该类的直接父类还没有被初始化,则先初始化其直接父类
          3. 假如类中有初始化语句,则系统依次执行这些初始化语句
      5. 类初始化时机:

      只有当对类的主动使用的时候才会导致类的初始化,类的主动使用包括以下六种:

        1. 创建类的实例,也就是new的方式
      
        2. 访问某个类或接口的静态变量,或者对该静态变量赋值
      
        3. 调用类的静态方法
      
        4. 反射
      
        5. 初始化某个类的子类,则其父类也会被初始化
      
        6. Java虚拟机启动时被标明为启动类的类,直接使用 java.exe命令来运行某个主类
      

      比如:测试类Test

  3. 使用: 当 JVM 完成初始化阶段之后,JVM 便开始从入口方法开始执行用户的程序代码

  4. 卸载: 当用户程序代码执行完毕后,JVM 便开始销毁创建的 Class 对象,最后负责运行的 JVM 也退出内存

利用类加载过程理解面试题
public class Test {
	public static void main(String[] args) {
		A a = A.getInstance();
        System.out.println("A value1:" + a.value1);//1
        System.out.println("A value2:" + a.value2);//0

        B b = B.getInstance();
        System.out.println("B value1:" + b.value1);//1
        System.out.println("B value2:" + b.value2);//1
	}
}
class A{
    private static A a = new A();
    public static int value1;	
    public static int value2 = 0;

    private A(){
        value1++;
        value2++;
    }

    public static A getInstance(){
        return a;
    }
}
class B{
    public static int value1;
    public static int value2 = 0;
    private static B b = new B();

    private B(){
        value1++;
        value2++;
    }
    public static B getInstance(){
        return b;
    }

}
类加载器

类加载器实现的功能是即为加载阶段获取二进制字节流的时候,在 Java 虚拟机外部实现,以便让应用程序自己决定如何去获取所需要的类。

面试题分析

分析一:

public class A {
	//准备阶段1:JVM给静态属性在静态区中开辟空间
	//A a;
	//int value1;
	//int value2;
	
	//准备阶段2:JVM给静态属性赋系统默认值
	//A a = null;
	//int value1 = 0;
	//int value2 = 0;
	
	//初始化阶段:java程序代码才开始真正执行
	//A a = new A();
	//int value1 = 1;
	//int value2 = 0;
	
	static A a = new A();
	static int value1;
	static int value2 = 0;
	
	public A() {
		value1++;
		value2++;
	}
	
}
public class Test01 {
	public static void main(String[] args) {
		
		System.out.println(A.value1);//1
		System.out.println(A.value2);//0	
	}
}

分析二:

public class A {
	//准备阶段1:JVM给静态属性在静态区中开辟空间
	//int value1;
	//int value2;
	//A a;
	
	//准备阶段2:JVM给静态属性赋系统默认值
	//int value1 = 0;
	//int value2 = 0;//0是系统赋的默认值
	//A a = null;

	//初始化阶段:java程序代码才开始真正执行
	//int value1 = 1;
	//int value2 = 1;
	//A a = new A();
	
	
	static int value1;
	static int value2 = 0;
	static A a = new A();
	
	public A() {
		value1++;
		value2++;
	}	
}
public class Test01 {
	public static void main(String[] args) {
		
		System.out.println(A.value1);//1
		System.out.println(A.value2);//1				
	}
}

理解:

Java万物皆对象!!!!!

一个class文件,对于Java来说,都是一个对象,而这个对象就是 class对象

class文件是什么?

class文件包含了该类的所有的信息

​ eg: 一个类有几个成员属性 一个类有几个静态属性? 一个类有几个构造方法属性 一个类有几个成员方法 等这些信息

class对象是什么????

class对象是class文件的访问入口

简答题

1.创建一个对象用什么运算符?对象实体与对象引用有何不同?

new 运算符,new 创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在

栈内存中)。一个对象引用可以指向 0 个或 1 个对象(一根绳子可以不系气球,也可以系一个气球);

一个对象可以有 n 个引用指向它(可以用 n 条绳子系住一个气球)。

12. 总结

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

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

注意:理解封装的概念

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

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

5.类加载机制(注重加载过程和面试题)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1392265.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法】算法(模拟、指针等)解决字符串类题目(C++)

文章目录 1. 前言2. 解决 字符串类算法题14.最长公共前缀5.最长回文子串67.二进制求和43.字符串相乘 1. 前言 字符串题目有很多种&#xff0c;这里筛选几个考察模拟、双指针等的题目&#xff0c;并用相关算法解决。 2. 解决 字符串类算法题 14.最长公共前缀 思路 题意分析&…

【Mybatis】说一下 mybatis 的一级缓存和二级缓存

​ &#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Mybatis ⛳️ 功不唐捐&#xff0c;玉汝于成 ​ 目录 前言 正文 一级缓存&#xff08;Local Cache&#xff09;&#xff1a; 范围&#xff1a; 生命周期&#xff1a; 默认开启&…

数据科学与大数据导论期末复习笔记(大数据)

来自于深圳技术大学&#xff0c;此笔记涵盖了期末老师画的重点知识&#xff0c;分享给大家。 等深分箱和等宽分箱的区别&#xff1a;等宽分箱基于数据的范围来划分箱子&#xff0c;每个箱子的宽度相等。等深分箱基于数据的观测值数量来划分箱子&#xff0c;每个箱子包含相同数量…

tcpdump常用参数以及wireshark密文解密

tcpdump常用参数以及wireshark密文解密 文章目录 一、tcpdump命令和常用参数二、在wireshark中协议解析 tcpdump常用参数 一、tcpdump命令和常用参数 tcpdump常用命令&#xff1a;tcpdump -i eth0 src host 11.6.224.1 and udp port 161 -s 0 -w 161.pcap &#xff08;161为sn…

(一)ROS的安装

&#xff08;一&#xff09;安装ubuntu18.04 系统&#xff08;虚拟机或者是物理机&#xff0c;在此不再介绍&#xff09; &#xff08;二&#xff09;添加ROS镜像源 apt 列表中没有ROS源&#xff0c;所以要手动添加 sudo sh -c . /etc/lsb-release && echo "deb…

mysql常见的需求,对于关键字的使用

如何使用MySQL将列数据转化为逗号分隔的形式。我们可以使用内置函数GROUP_CONCAT()来实现这个功能 如何使用MySQL将列数据转化为逗号分隔的形式。我们可以使用内置函数GROUP_CONCAT()来实现这个功能&#xff0c;也可以根据实际需求自定义一个函数。这种技术在一些需要对数据进…

imgaug库指南(28):从入门到精通的【图像增强】之旅(万字长文)

引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应运而生&#xff0c;成为了解决这一问题的…

linux-nfc neard 编译与安装

项目github地址&#xff1a; https://github.com/linux-nfc/neard git clone地址&#xff1a; https://github.com/linux-nfc/neard.git clone完源码切换到目录neard里。这个项目需要依赖一下库&#xff1a; - GCC compiler - D-Bus library - GLib library - Netlink (lib…

go语言(一)----声明常量

package mainimport ("fmt""time" )func main() {fmt.Print("hello go!")time.Sleep(1 * time.Second)}运行后&#xff0c;结果如下&#xff1a; 1、golang表达式中&#xff0c;加&#xff1b;和不加&#xff1b;都可以 2、函数的{和函数名一…

.net core 6 使用注解自动注入实例,无需构造注入 autowrite4net

像java使用autowrite一样使用 1、前提先注册到ioc容器当中 builder.Services.AddScoped 2、nuget引入AutoWrite4Net 3、启用 //启用自动注入 app.UseAutoWrite(); 4、在类上使用注解 [StartAutoWrite] public class NacosController : ControllerBase 5、实例上使用注解 …

【Linux】nc 网络诊断 | 文件传输 命令详解

目录 一、命令简介 二、命令使用 2.1 测试服务器 2.2 端口连通性测试 2.2.1tcp端口连通性测试 2.2.2udp端口连通性测试 2.3 文件及目录的传输 2.3.1 文件传输(TCP端口) 2.3.2 文件传输(UDP端口) 相关文章&#xff1a; 【网络】抓包工具Wireshark下载安装和基本使用教…

强化加密生态合规性:Token Explorer 助你一臂之力!

随着加密市场监管的不断加强&#xff0c;项目的合规风险可能会在一夜之间威胁到其可行性。然而&#xff0c;通过智能的分析技术进行全面的代币审计&#xff0c;可以帮助我们及时发现问题&#xff0c;保护项目的声誉。 Token Explorer 提供智能的专业分析&#xff0c;让我们了解…

linux安装QQ(官方正版)

QQ官网上有支持linux系统的版本&#xff0c;所以去官网直接下载正版就好。 安装步骤&#xff1a; 1.进入官网&#xff1a;https://im.qq.com/linuxqq/index.shtml 2.选择版本&#xff1a;X86版下载dep 如下所示&#xff1a; 3.下载qq安装包&#xff1a; 4.使用命令安装qq s…

高考志愿填报系统开发技术语言选择总结

开发高考志愿填报系统&#xff0c;需要考虑到系统的稳定性、安全性、易用性以及数据准确性。以下是针对高考志愿填报系统的技术方案选择建议&#xff1a; 1.后端技术&#xff1a;可以使用Python、Java、PHP等后端语言进行开发&#xff0c;考虑到易用性和开发效率&#xff0c;可…

MetaGPT学习笔记 - task1task2

章节&#xff1a;task1&task2 一.github地址&#xff1a;github.com/geekan/MetaGPT 二.MetaGPT: 多智能体框架​ 使 GPT 以软件公司的形式工作&#xff0c;协作处理更复杂的任务 MetaGPT输入一句话的老板需求&#xff0c;输出用户故事 / 竞品分析 / 需求 / 数据结构 / A…

UI设计中插画赏析和产品色彩分析

插画赏析&#xff1a; 1. 插画是设计的原创性和艺术性的基础 无论是印刷品、品牌设计还是UI界面&#xff0c;更加风格化的插画能够将不同的风格和创意加入其中&#xff0c;在激烈的竞争中更容易因此脱颖而出。留下用户才有转化。 2. 插画是视觉触发器&#xff0c;瞬间传达大量…

React16源码: React中的异步调度scheduler模块的源码实现

React Scheduler 1 ) 概述 react当中的异步调度&#xff0c;称为 React Scheduler发布成单独的一个 npm 包就叫做 scheduler这个包它做了什么&#xff1f; A. 首先它维护时间片B. 然后模拟 requestIdleCallback 这个API 因为现在浏览器的支持不是特别的多所以在浏览当中只是去…

【报错】NVIDIA 驱动版本不兼容 — NVIDIA driver on your system is too old

【报错】NVIDIA 驱动版本不兼容 — NVIDIA driver on your system is too old 报错信息查看torch版本查看nvidia驱动版本 报错信息 CUDA initialization: The NVIDIA driver on your system is too old (found version 11040). Please update your GPU driver by downloading …

投资半导体行业可靠吗?九方智投洪帮主助投资者深度剖析市场

近期,CES2024展会火热袭来,作为行业内知名活动,展会的官方数据显示本次参展企业达到了4000家。作为CES2024的特色主题,人工智能有望成为会议的重大亮点。 人工智能涉及到的领域包含方方面面,其中AI软件和硬件解决方案的发布将促进半导体行业需求,算力芯片和边缘侧AI的机会值得关…

纯前端实现加减运算验证码

纯前端实现加减运算验证码 实现效果 //页面展示 <template><view class"form-input-item" style"padding:8rpx 22rpx;"><input class"form-input" placeholder"请输入验证码" type"text" maxlength"6…