public class Demo{
public static void main(String[] args) {
Person p1 = new Person("zhangsan");
Person p2 = new Person("lisi");
p1.show();
System.out.println(Person.country);//静态成员直接被类名调用
}
}
class Person{
String name;//成员变量,实例变量
static String country = "CN";//静态的成员变量,类变量
Person(String name){
this.name = name;
}
void show(){
System.out.println(name + ":" + country);
}
}
见下图,country前面加static,则会被放置于共享区;如果country前面不加static,则会在每个对象中存在country=“CN”:
类变量随着类的加载而存在于方法区中;
实例变量随着对象的建立而存在于堆内存中。
类变量生命周期最长, 随着类的消失而消失;
实例变量生命周期随着对象的消失而消失。
1.静态方法只能访问静态成员,非静态方法既可以访问静态,也可以访问非静态;
2. 静态方法中不可以定义this、super关键字,因为静态优先于对象存在;
3. 主函数是静态的。
利处:对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象中都存储一份、可以直接被类名调用;
弊端:生命周期过长、访问有局限性(只能访问静态)。
public static void main(String[] arg)
public:代表该函数的访问权限是最大的;
static:代表主函数随着类的加载就已经存在了;
void:主函数没有具体的返回值;
main:不是关键字,但是是一个特殊的单词,可以被jvm识别;
String[] args:args(arguments),函数的参数,参数类型是一个数组,该数组中的元素是字符串。字符串类型的数组;
主函数是固定格式的,被jvm所识别,jvm在调用主函数时,传入的是new String[0]。
public class Demo{
public static void main(String[] args){
System.out.println(args);//输出 [Ljava.lang.String;@135fbaa4
System.out.println(args.length);//输出 0
}
}
命令行中使用java命令启动虚拟机执行Demo类时,其会调用该类中的main函数,在后面可以传入字符串,见下图:
public class Demo{
public static void main(String[] args){
System.out.println(args[0]);
System.out.println(args.length);
}
}
当对象中出现共享数据时,该数据被静态所修饰;对象中的特有数据定义为非静态,存在于堆内存中。
当功能内部没有访问到非静态数据(对象的特有数据),该功能可以定义为静态的。
//需要定义为静态函数
public class Demo{
public static void main(String[] args){
Person.show();//不建立对象,直接使用类调用函数
}
}
class Person{
String name;
//未使用非静态数据,定义为静态函数
//因为未使用静态数据,所以当只需要单独执行此函数时,
//建立对象是多余的,需要不建立对象也可调用此函数,所以定义为静态函数
public static void show(){
System.out.println("Person");
}
}
//不能定义为静态函数
public class Demo{
public static void main(String[] args){
Person p1 = new Person();
p1.show();
}
}
class Person{
String name;
//使用非静态数据,不能定义为静态函数
public void show(){
System.out.println("Person:" + name);//需要打印姓名(非静态数据)
}
}
每一个应用程序中都有共性的功能,可以将这些功能进行抽取,独立封装,以便复用。
Demo.java文件:
/*
虽然可以通过建立ArrayTools的对象使用这些方法对数组进行操作,但是:
1.对象适用于封装数据的,但是ArrayTools对象并未封装特有数据;
2.操作数组的每一个方法都没有用到ArrayTools对象中的特有数据。
此时,考虑到程序更严谨,是不需要对象的,可以将ArrayTools中的方法定义为static的,直接通过类名调用即可。
将方法都静态后,可以方便使用,但是该类还是可以被其他程序建立对象的,为了更加严谨,强制该类不能建立对象,可以将构造函数私有化:private ArrayTools(){}。
*/
public class Demo{
public static void main(String[] args){
int[] array = {44,41,43,45,46};
System.out.println("max = " + ArrayTools.getMax(array));//直接类名调用,不用生成对象
System.out.println("min = " + ArrayTools.getMin(array));
ArrayTools.printArray(array);
ArrayTools.selectSort(array);
ArrayTools.printArray(array);
int index = ArrayTools.binarySearch(array, 40);
System.out.println(index);
/* ArrayTools tools = new ArrayTools();
int[] array = {44,41,43,45,46};
System.out.println("max = " + tools.getMax(array));
System.out.println("min = " + tools.getMin(array));
tools.printArray(array);
tools.selectSort(array);
tools.printArray(array);
int index = tools.binarySearch(array, 40);
System.out.println(index);*/
}
}
ArrayTools.java文件:
/**
* Created by hacker on 2017/9/22.
*/
public class ArrayTools {
private ArrayTools(){}//构造函数私有化
public static int getMax(int[] array){//求数组最大值
int max = 0;
for(int i=1; iif(array[i] > array[max])
max = i;
}
return array[max];
}
public static int getMin(int[] array){//求数组最小值
int min = 0;
for(int i=1; iif(array[i] < array[min])
min = i;
}
return array[min];
}
public static void printArray(int[] array){//输出数组
System.out.printf("[");
for(int i=0; iif(i != array.length - 1)
System.out.print(array[i] + ", ");
else
System.out.println(array[i] + "]");
}
}
public static void selectSort(int[] array){//选择排序
for(int i=0; i1; i++){//遍历数组
for(int j=i+1; jif(array[j] < array[i]) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
public static void bubbleSort(int[] array){//冒泡排序
for (int i=0; i1; i++)
for(int j=0; j1-i; i++){
if(array[j] > array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
public static int binarySearch(int[] array, int num){//二分法/折半查找法
int min = 0;
int max = array.length - 1;
int mid = (min + max) / 2;
while(min <= max) {
if (array[mid] < num) {
min = mid + 1;
mid = (min + max) / 2;
} else if (array[mid] > num) {
max = mid - 1;
mid = (min + max) / 2;
} else
return mid;
}
return -1;
}
}
如果将ArrayTools.class文件发送给其他人,其他人只需要将该文件设置到classpath的路径下,就可以使用该工具类,但是对方不清楚该类中定义了多少方法,所以需要制作程序使用说明书,java的说明书通过文档注释来完成。
注意:私有的方法不会被提取到帮助文档。
/**
对数组进行操作的工具类,提供了获取最大值、最小值、输出数组、选择排序、冒泡排序、折半查找法功能。
@author 高世皓
@version V1.0
*/
public class ArrayTools {
/**
空参数构造函数,被私有化
*/
private ArrayTools(){}
/**
获取一个整形数组中的最大值
@param array 接收一个int类型的数组
@return 会返回一个该数组中的最大值
*/
public static int getMax(int[] array){
int max = 0;
for(int i=1; iif(array[i] > array[max])
max = i;
}
return array[max];
}
/**
获取一个整形数组中的最小值
@param array 接收一个int类型的数组
@return 会返回一个该数组中的最小值
*/
public static int getMin(int[] array){
int min = 0;
for(int i=1; iif(array[i] < array[min])
min = i;
}
return array[min];
}
/**
打印一个整形数组中的元素
@param array 接收一个int类型的数组
*/
public static void printArray(int[] array){
System.out.printf("[");
for(int i=0; iif(i != array.length - 1)
System.out.print(array[i] + ", ");
else
System.out.println(array[i] + "]");
}
}
/**
选择排序,对一个整形数组按照从小到大的顺序排序
@param array 接收一个int类型的数组
*/
public static void selectSort(int[] array){
for(int i=0; i1; i++){//遍历数组
for(int j=i+1; jif(array[j] < array[i]) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
/**
冒泡排序,对一个整形数组按照从小到大的顺序排序
@param array 接收一个int类型的数组
*/
public static void bubbleSort(int[] array){
for (int i=0; i1; i++)
for(int j=0; j1-i; i++){
if(array[j] > array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
/**
二分法/折半查找法,查找某个数值在整形数组中的位置,没有返回-1
@param array 接收一个int类型的数组
@param num 要查找的数值
@return 返回查找到的位置索引
*/
public static int binarySearch(int[] array, int num){
int min = 0;
int max = array.length - 1;
int mid = (min + max) / 2;
while(min <= max) {
if (array[mid] < num) {
min = mid + 1;
mid = (min + max) / 2;
} else if (array[mid] > num) {
max = mid - 1;
mid = (min + max) / 2;
} else
return mid;
}
return -1;
}
}
使用命令javadoc -d myHelpDoc ArrayTools.java -author -version生成说明书,注意myHelpDoc为文件夹的名称,如果该目录下没有该文件夹,则会自动生成一个。
static{
静态代码块中的执行语句。
}
随着类的加载而运行,只执行一次,并优先于主函数,用于给类进行初始化的。
eg1:
/*
b
c
a
end
*/
class staticCode{
static{
System.out.println("a");
}
}
class Demo{
static{
System.out.println("b");
}
public static void main(String[] args){
new staticCode();
new staticCode();//此时类已经加载了,不再执行静态代码块
System.out.println("end");
}
static{
System.out.println("c");
}
}
eg2:
/*
a
show code
*/
class staticCode{
static{
System.out.println("a");
}
public static void show(){
System.out.println("show code");
}
}
class Demo{
public static void main(String[] args){
staticCode.show();
}
}
eg3:
/*
静态代码块
构造代码块, num = 2
构造函数2
*/
class staticCode{
int num = 2;
{//给对象初始化
System.out.println("构造代码块" + ", num = " + num);
}
static{//给类初始化,不能访问num,因为num为非静态变量
System.out.println("静态代码块");
}
staticCode(){
System.out.println("构造函数1");
}
staticCode(int x){
System.out.println("构造函数2");
}
public static void show(){
System.out.println("show code");
}
}
class Demo{
public static void main(String[] args){
new staticCode(4);
}
}
public class Demo{
public static void main(String[] args){
Person p = new Person("liming", 23);
p.show();
}
}
class Person{
private String name = "shgao";
private int age;
private static String country = "CN";
{//给对象初始化
System.out.println("构造代码块");
}
static {//给类初始化
System.out.println("静态代码块");
}
Person(String name, int age){
this.name = name;
this.age = age;
System.out.println("构造函数初始化");
}
void show(){
System.out.println("name: " + name + ", " +
"age: " + age + ", country: " + country);
}
}
Person p = new Person("liming", 23);
1.new用到了Person.class,会找到Person.class文件并加载到内存中;
2.执行该类中的静态代码块和静态变量初始化,给类进行初始化,顺序由上至下;
3.在堆内存中开辟空间,分配内存地址;
4.在堆内存中建立对象的特有属性,并进行默认初始化(0 null);
5.对对象进行显示初始化;
5.对对象进行构造代码块初始化;
6.对对象进行对应的构造函数初始化;
7.将内存地址赋值给栈内存中的p变量。