一.内存中做了哪些事物
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中,使用{}包裹起来的代码,都称为"代码块"
代码块的分类:
-
局部代码块:
在局部位置(方法定义中){xx},
作用:限定局部变量的生命周期,不能超过这个范围访问 -
构造代码块:
在类的成员位置中使用{}包裹起来的代码,
作用:将多个构造方法中相同的代码存储在构造代码块中,在执行构造方法之前先执行,对数据进行初始化!特点:每次执行构造方法之前,如果存在构造代码块,优先执行构造代码块,在执行构造方法!
-
静态代码块:
在类的成员位置:
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()) ;
}
}