Java学习_day09_(创建对象时java内存都做了什么、static关键字、文档说明书制作、代码块、成员变量定义时机)

本文详细探讨了Java内存中的对象创建过程,包括加载类、分配内存、初始化对象等步骤。同时,深入讲解了static关键字的作用,强调了静态成员的共享特性以及在类加载时的生命周期。此外,介绍了如何制作工具类,包括私有构造方法和静态方法的使用,以及编写文档注释的最佳实践。最后,讨论了代码块的概念,包括局部、构造和静态代码块的执行顺序,并给出了成员变量定义的时机指导。
摘要由CSDN通过智能技术生成

一.内存中做了哪些事物

Student s = new Student();在内存里都做了什么?

1.加载student.class这个学生类.
2.在栈内存中开辟占内存空间为这个变量 s
3.在堆内存申请空间
4.给学生类的属性系统默认初始化,通过执行学生类的无参构造方法
5.产生一个堆内存空间地址
6.将堆内存空间地址赋值给栈内存变量 s
7.栈内存变量s 就指向这个堆内存地址

jvm来调用:
main所在的线程"用户线程"
GC: 垃圾回收器,开启垃圾回收线程
目的:回收没有更多引用的对象
在这里插入图片描述

二. static关键字

static关键字最基本的特点:可以被多个对象"共享、共用"
被static修饰的优先于对象存在,随着类的加载而加载然后进内存,static关键字不能和this共存

特点:
1)static 随着类的加载而加载 (生命周期----->xxx.class :static相关的都先进内存! )
2)优先于对象存在
类的加载:类名.class (优先的)
对象的创建:类名 对象名 =new 类名() ;

3)不能和this共用!
4)被静态修饰的变量/方法—>(称为 “静态变量”,“静态方法”):有共享,共用的意思
举例:
水杯中的水 :不能被共用的
饮水机:可以被共用!
5)被静态修饰的变量或者方法,推荐使用的类名访问
类名.静态变量名;
类名.静态方法名() ;

不推荐使用:类名 对象名 = new 类名() ;
对象名.静态变量名;
对象名.静态方法名() ;

//Demo类
class Demo{
	
	//成员变量
	int num = 10 ;
	
	//静态变量
	static int num2 = 20 ;
	
	
	//成员方法
	public void function(){
		System.out.println("function demo...") ;
	}
	
	//静态方法
	public static void method(){
		System.out.println("method demo...") ;
	}
}

//测试类
class StaticDemo{

	public static void main(String[] args){
		
		//需求:要访问Demo类中的num和num2变量?
		Demo d = new Demo() ;
		System.out.println(d.num) ;
		//System.out.println(d.num2) ; //静态变量不这样访问:不推荐!
		System.out.println(Demo.num2) ; //静态的成员的访问方式
		
		System.out.println("---------------------") ;
		d.function() ;
		//d.method() ;//不推荐
		//推荐方式
		Demo.method() ;	
	}
}

在这里插入图片描述
关于static静态的使用注意事项:
1)非静态的成员方法:
可以访问静态的成员变量,也可以访问非静态的变量!
包括静态方法或者非静态方法

简单记: 非静态的可以访问静态的成员/非静态的…
2)静态的方法
静态只能访问静态! (这些静态变量/方法都是跟类相关的!)

//Demo类
class Demo{//Demo.class
	//静态
	public static int number = 100 ;
	//非静态
	public int number2 = 20 ;
	
	//非静态的成员方法
	public void show(){
		System.out.println(number2) ;
		System.out.println(number) ;
		System.out.println("-------------------") ;
		function() ;//静态方法
		method() ;
	}
	
	public void method(){
		System.out.println("method demo") ;
	}
	
	//静态方法
	public static void function(){
		//System.out.println(number2) ; //无法从静态上下文中引用非静态 变量 number2
		System.out.println(number) ;
		System.out.println("function demo") ;
		
		//method() ;//无法从静态上下文中引用非静态 方法 method()
	}
}

三. 文档说明书制作(工具类)

工具类:就是为了便于程序员使用,使用简单,而且不需要new ,都是将构造方法私有化,外界不能访问
工具类中所有的功能都是static的(静态) :类名.方法名();

针对数组的操作的功能: 都提供出来
1)遍历
2)最值
3)获取元素角标值
4)冒泡排序…

在每一个功能上加入 文档注释

class ArrayTool{


	//将构造方法私有化了
	private ArrayTool(){
	}

	//提供数组的遍历功能
	
	//需要静态使用
	public static  void printArray(int[] arr){
		System.out.print("[") ;
		//遍历数组
		for(int x = 0 ; x < arr.length ; x ++){
			//判断
			if(x == arr.length-1){
				System.out.println(arr[x] +"]") ;
			}else{
				System.out.print(arr[x]+", ") ;
			}
		}
	}
}

定义一个数组,静态初始化,使用功能遍历数组
在测试类中使用这个功能

class ArrayDemo{
	public static void main(String[] args){
		
		
		//创建一个数组,静态初始化
		int[] arr = {66,15,78,45,23} ;
		
		//功能遍历数组
		//printArray(arr) ;  //静态访问静态
		
		
		//去了static关键字:main方法中不能直接非静态的方法
		//使用类名 对象名 = new 类名() ;
	//	ArrayDemo ad = new ArrayDemo() ;
		//ad.printArray(arr) ;
		
		//弊端:上面不好的原因:测试类中应该出现的其他类以及这个类的功能,而不能使用自己本身去调用功能!
		
		
		//测试ArrayTool类,并且测试里面 相关的功能
		//创建ArrayTool类对象,访问功能
		//ArrayTool at = new ArrayTool() ; 
		//at.printArray(arr) ;
		
		//ArrayTool() 在 ArrayTool 中是 private 访问控制:
		//将ArrayTool的构造方法私有化:目的就是保证安全性,外界不能直接new
		
		//类名.方法名() ;
		ArrayTool.printArray(arr) ;
		
	}
	
	//去掉了static关键字
	/*
	public   void printArray(int[] arr){
		System.out.print("[") ;
		//遍历数组
		for(int x = 0 ; x < arr.length ; x ++){
			//判断
			if(x == arr.length-1){
				System.out.println(arr[x] +"]") ;
			}else{
				System.out.print(arr[x]+", ") ;
			}
		}
	}
	*/
	
	
	/*
	//定义一个遍历数组的功能
	public static  void printArray(int[] arr){
		System.out.print("[") ;
		//遍历数组
		for(int x = 0 ; x < arr.length ; x ++){
			//判断
			if(x == arr.length-1){
				System.out.println(arr[x] +"]") ;
			}else{
				System.out.print(arr[x]+", ") ;
			}
		}
	}
	*/
}

写法:

	/**
		这个功能是针对数组的遍历功能,将元素一一获取出来
		最终的结果是[元素1, 元素2, 元素3, ...] 
		
		@param  arr  这个参数是将指定的数组进行遍历 
		
	
	*/
	public static  void printArray(int[] arr){
		System.out.print("[") ;
		//遍历数组
		for(int x = 0 ; x < arr.length ; x ++){
			//判断
			if(x == arr.length-1){
				System.out.println(arr[x] +"]") ;
			}else{
				System.out.print(arr[x]+", ") ;
			}
		}
	}
	
	/**
		该功能是获取数组中的最大值
		@param arr  在指定对数组中查找最大值
		@return  返回就是获取的数组中的最大值max
	*/
	public static int getMax(int[] arr){
		//参照物
		int max = arr[0] ; 
		for(int x = 1 ; x < arr.length ; x ++){
			if(arr[x] > max){
				max = arr[x] ;
			}
		}
		return max ;
	}
	
	/**
		该功能是查询指定的元素在数组中出现的索引值
		@param arr  当前在指定的数组中查找
		@param key  要查找的指定的元素
		@return 返回查询到的元素在数组中的索引值
	*/
	public static int getIndex(int[] arr,int key){
		//使用假设法
		int index = -1 ;
		for(int x = 0 ;  x < arr.length ; x ++){
			//判断
			if(arr[x] == key){
				index = x ; 
				break ;
			}
		}
		
		return index ; 
	}
	/**
		这个功能是对数组进行冒泡排序
		@param arr  对指定的数组进行排序
	*/
	public static void bubbleSort(int[] arr){
		for(int x = 0 ; x < arr.length -1 ; x ++){
			for(int y = 0 ; y < arr.length-1-x ; y ++){
				if(arr[y] > arr[y+1]){
					int temp = arr[y] ;
					arr[y] = arr[y+1] ;
					arr[y+1] = temp ;
				}
			}
		}
	}	
}

产生文档说明书:针对ArrayTool.java文件产生API 文档解析
进入到本地目录下:
使用javadoc -d doc(目录名字) -author -version ArrayTool.java(针对哪个Java文件产生文档解析)

以后使用的API (Application Programming Interface)
打开jdk提供的JDK6/JDK7/JDK8: 文档之后,点击索引 “输入你要查询的类或者接口”

进去之后:
看这个类的字段(成员变量)
构造方法:有几种方式创建该类对象
方法(成员方法):有哪些功能

//测试类
class ArrayDemo{
	public static void main(String[] args){
		
		
		//创建一个数组,静态初始化
		int[] arr = {66,15,78,45,23} ;
		
		//使用类名.访问方法名即可
		ArrayTool.printArray(arr) ;
		System.out.println("--------------") ;
		int max = ArrayTool.getMax(arr) ;
		System.out.println("数组中的最大值是:"+max) ;
		System.out.println("--------------") ;
		int index = ArrayTool.getIndex(arr,45) ;
		System.out.println("index:"+index) ;
		System.out.println("--------------") ;
		ArrayTool.bubbleSort(arr) ;
		ArrayTool.printArray(arr) ;
		
	}	
	
}

四. 什么是代码块,以及代码块的分类

代码块:在Java中,使用{}包裹起来的代码,都称为"代码块"

代码块的分类:

  1. 局部代码块:
    在局部位置(方法定义中){xx},
    作用:限定局部变量的生命周期,不能超过这个范围访问

  2. 构造代码块:
    在类的成员位置中使用{}包裹起来的代码,
    作用:将多个构造方法中相同的代码存储在构造代码块中,在执行构造方法之前先执行,对数据进行初始化!

    特点:每次执行构造方法之前,如果存在构造代码块,优先执行构造代码块,在执行构造方法!

  3. 静态代码块:
    在类的成员位置:
    static{

    }

    静态随着类的加载而加载,类加载一次,静态代码块就执行一次
    静态代码块优先执行!

构造代码块,构造方法,静态代码块的优先级
静态代码块 > 构造代码块 > 构造方法 !

//定义一个类Code
class Code{
	//静态代码块
	static{
		int x = 1000 ;
		System.out.println(x) ;
	}

	//构造代码块
	{
		int x = 100 ;
		
		System.out.println(x) ; 
	}
	
	//无参构造方法
	public Code(){
		System.out.println("code...") ;
	}
	//有参构造
	public Code(int num){
		System.out.println("code"+num) ;
	}
	
	//构造代码块
	{
		int y = 200 ;
		System.out.println(y) ;
	}
	static{
	
		int y = 2000 ;
		System.out.println( y ) ;
	}	
}

//测试类
class CodeDemo{
	public static void main(String[] args){
		
		//局部代码块
		{
			int x = 10 ;
			System.out.println(x) ;//10
		}
		System.out.println("------------------") ;
		
		//System.out.println(x) ;无法变量x
		
		//创建Code类对象
		Code c = new Code() ;
		
		System.out.println("------------------") ;
		Code c2 = new Code(10) ;
	}
}

输出:

10                  
------------------
1000	//Code() c= new Code();创建对象会加载类,静态代码块随着类的加载而加载,
		//类只加载一次,所以静态代码块只运行一次
2000

100		//构造代码块先于构造方法,后于静态代码块运行
200
code...		//构造方法(无参)
------------------
100		//再执行一次构造代码块..........Code c2 = new Code();
200
code10	//构造方法(有参)

五.成员变量定义时机问题

如果当前这个变量能够描述真实事物的属性,这个时候将变量定义成员变量

而如果不能够体现出现真实事物的属性,将变量定义局部变量;
没有明确要求的情况下,都优先定义为局部变量,局部变量随着方法调用而存在,随着方法调用结束而消失!

需求:
定义一个Demo类中,在类中定义一个功能,求两个数据之和!

方式1和方式2都可以完成需求:
方式2弊端:将a,b定义为成员变量, 什么时候将变量定义成员变量

//Demo类
//方式1 (推荐第一种)

class Demo{
	
	//成员方法
	public int sum(int a,int b){
		return a + b ;
	}
}


//方式2:
//将a,b这两个变量:放在类中,作为成员变量
/*
class Demo{
	int a ;
	int b ; 
	//求和
	public int sum(){
		return a + b ;
	}
}
*/


//测试类
class VariableDemo{
	public static void main(String[] args){
		//测试
		//创建Demo类的对象来访问sum方法
		
		Demo demo = new Demo() ;
		int  result = demo.sum(10,20) ;
		System.out.println("result:"+result) ;
		
		
		//方式2
		/*
		//创建Demo类对象
		Demo d = new Demo() ;
		d.a = 10 ;
		d.b = 40 ;
		int result = d.sum() ;
		System.out.println("result:"+result) ;
		*/
	}
}

需求:
长方形:
键盘录入长方形的长和宽,分别求出这个长方形的周长和面积!
分析:
长方形是真实事物:
两个属性:长和宽 ----长和宽定义为成员变量(私有修饰)
周长和面积: 长方形事物的行为!

定义一个长方形类(Ract)
length和width

import java.util.Scanner ;


class Ract{
	//成员变量
	private int length ; //长
	private int width ; //宽
	
	//set方法赋值
	public void setLength(int length){
		this.length = length ; 
	}
	public void setWidth(int width){
		this.width = width ;
	}
	
	//求周长的功能
	public int getZhouChang(){
		return (length+width)*2;
	}
	//求面积
	public int getArea(){
		 return length * width ;
	}
}

//测试类
class Test{

	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() ;
		
		//封装长方形类
		Ract r = new Ract() ;
		r.setLength(length) ;
		r.setWidth(width) ;
		
		//输出
		System.out.println("该长方形的周长是:"+r.getZhouChang()) ;
		System.out.println("该长方形的面积是:"+r.getArea()) ;
	}
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值