java之6天 static代码块,单例模式

static(静态) 关键字

//用于修饰成员(成员变量和成员函数)

//被static修饰后的特点
  1.随着类的加载而加载,消失而消失(说明生命周期随着类)
  2.优先于对象存在
  3.被所有对象共享
  4.可以直接被类名调用
  5.静态变量定义多了,就会消耗更多的内存 


//实例变量 和 类变量(静态变量)的区别
  1.存放位置
     类变量随着类的加载而存在方法区中
     实例变量随着对象的建立存在与堆内存中
  2.生命周期
    类变量的生命周期最长:  随着类的消失而消失
    实例变量生命周期随着对象的消失而消失
  

//使用注意
  1.静态方法只能访问静态成员(方法和变量)
    非静态可以访问静态也可以访问非静态

  2.静态方法中不可以写 this,super 关键字
      因为静态优先于对象存在,所以静态方法中不可以出现this.

  3.主函数是静态的.

//静态有利有弊
  利: 对对象共享数据进行单独空间的存储,节省空间,没有必要每个对象中都存储一份.
      可以直接被类名调用.

  弊端:生命周期过长
       访问出现局限性(静态虽好,只能访问静态)



static 的使用 为了节约内存的使用  (如果多个对象拥有同样的属性)

class Person{
  String name;  //成员变量,实例变量
  static String country="CN";  //静态的成员变量,类变量
  public void show(){
   System.out.println(name+":::"+country);
  }

}

/**
主函数: 是一个的特殊的函数,作为程序的入口,可以被JVM调用

主函数的定义: 
public: 代表着该函数访问权限是最大的.
static: 代表着主函数随着类的加载 就已经存在了.
void:   主函数没有具体的返回值.
main: 不是关键字,但是是一个特殊的单词,可以JVM识别
String[] args: 函数的类型,参数类型是一个数组,该数组中的元素是一个字符串,字符串类型的数组.
主函数是固定格式的:JVM识别.
args:arguments : 就只有这个变量名可以 修改

JVM再调用主函数时, 传入的是new String[0];
*/

public static void main(String[] args){


}
//重载
public static void main(int x){}

//重载
public static void main(String[] args,int x){ }


DOS 中 给 main传递 参数
c:\> javac MainDemo.java

c:\> java MainDemo haha hehe heihei xixi wuwu   

//还一种 给main传递参数

class MainDemo{

     public static void main(String[] args){
        
      String [] arr={"hah","hehe","heihei","xixi","wuwu","hiahia"};
     
         MainTest.main(arr);
     }
}

class MainTest{

   public static void main(String[] args){
     for(int x=0;x<args.length;x++)
       System.out.println(args[x]);

   }

}



//什么时候使用静态??
要从两方面下手 
因为静态修饰的内容有成员变量和函数

//什么时候定义静态的变量(类变量)呢?
  当对象中出现共享数据时, 该数据被静态所修饰 存在方法区中.
   对象中的特有数据要定义成非静态存在于堆内存中

//什么时候定义静态的函数呢?
  当功能内部没有访问到非静态数据(对象的特有数据)
   那么该功能可以定义成静态的.

//静态的应用
  //对象是用来封装数据的,如果某个方法没有使用到 对象中的特有数据,就可以定义成static的 

//为了是某个类不然用户建立对象, 可以见构造函数私有化 .


/**
一个类中默认会有一个空参数的构造函数
这个默认的构造函数的权限恶化所属类一致.

1.如果类的被public 修饰,那么默认的构造函数,也带有public 修饰符

2.如果类没有被public修饰,那么默认的构造函数,也没有public修饰.

默认的构造函数的权限是随着类的变化而变化的
*/


帮助文档的制作

/使用  javadoc 来创建java类的说明书 
c:\> javadoc -d c:\javadoc  -author -version  MyTools.java

在c:\javadoc 中 创建 MyTools工具类的 说明书 

//注意 :  要生成说明书的类必须 是public 修饰


/**
 * 自定义 数组的 和 进制转换 工具类
 * @author Bin
 * @version V1.1
 */
public class MyTools {
	 
	private MyTools() {
	}

	/**
	 * 获取最大值 采用 元素值表示
	 * 
	 * @param arr
	 *            接受一个int 类型的数组
	 * @return 返回该数组中的最大值
	 */
	public static int getArrMax(int[] arr) {

		int max = arr[0];
		for (int x = 0; x < arr.length; x++) {
			if (arr[x] > max)
				max = arr[x];
		}
		return max;
	}

	/**
	 * 获取数组的最小值
	 * 
	 * @param arr
	 * @return
	 */
	public static int getArrMin(int[] arr) {

		int max = 0;
		for (int x = 0; x < arr.length; x++) {
			if (arr[x] < arr[max])
				max = x;
		}
		return arr[max];
	}

	/**
	 * 选择排序
	 * 
	 * @param arr
	 */
	public static void selSort(int[] arr) {

		for (int x = 0; x < arr.length; x++) {

			for (int y = x; y < arr.length; y++) {
				if (arr[x] < arr[y]) {
					int temp = arr[x];
					arr[x] = arr[y];
					arr[y] = temp;
				}

			}
		}
	}

	/**
	 * 冒泡排序
	 * 
	 * @param arr
	 */
	public static void bubbleSort(int[] arr) {

		for (int x = 0; x < arr.length - 1; x++) {
			// -x:让每一次比较的元素减少,-1 :不让下标越界
			for (int y = 0; y < arr.length - 1 - x; y++) {
				if (arr[y] > arr[y + 1]) {
					swarp(arr, y, y + 1);
				}
			}
		}

	}

	/**
	 * 交换数组中的两个位置
	 * 
	 * @param arr
	 *            接受一个int类型的数组
	 * @param a
	 *            要换的位置1
	 * @param b
	 *            要换的位置2
	 */
	private static void swarp(int arr[], int a, int b) {
		/*
		 * //方法一: int temp=arr[a]; arr[a]=arr[b]; arr[b]=temp;
		 */

		// 方法二
		arr[a] = arr[a] ^ arr[b];
		arr[b] = arr[a] ^ arr[b];
		arr[a] = arr[a] ^ arr[b];
	}

	/**
	 * 获取key 第一次出现的位置 -1 表示数组中不存在
	 * 
	 * @param arr
	 * @param key
	 * @return
	 */
	public static int getIndex(int[] arr, int key) {
		for (int x = 0; x < arr.length; x++) {
			if (arr[x] == key)
				return x;
		}
		return -1;// 没有找到

	}

	/**
	 * 折半查找 必须保证数据中的元素是有序的 折半查找方式1,提高效率,但是必须要保证该数组是有序的数组
	 * 
	 * @param arr
	 * @param key
	 * @return
	 */
	public static int halfSearch(int[] arr, int key) {
		int min = 0;
		int max = arr.length - 1;
		int mid = (max + min) / 2;

		while (arr[mid] != key) {
			if (key > arr[mid])
				min = mid + 1;
			else if (key < arr[mid])
				max = mid - 1;

			if (min > max)
				return -1;
			mid = (max + min) / 2;
		}
		return mid;
	}

	/**
	 * 折半查找 2 折半查找方式可以用于插入 数据
	 */
	public static int halfSearch_2(int[] arr, int key) {
		int min = 0, max = arr.length, mid;

		while (min <= max) {
			mid = (min + max) >> 1;
			if (key > arr[mid])
				min = mid + 1;
			else if (key < arr[mid])
				max = mid - 1;
			else
				return mid;
		}
		return -1;

	}

	/**
	 * 各种进制的转换
	 * 
	 * @param num
	 * @param base
	 *            与上的基数
	 * @param offset
	 *            偏移量
	 * @return
	 */
	private static String trans(int num, int base, int offset) {
		char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
				'B', 'C', 'D', 'E', 'F' };
		if (num == 0)
			return "0";
		StringBuffer sb = new StringBuffer();
		while (num != 0) {
			int temp = num & base;
			sb.append(chs[temp]);
			num = num >>> offset;
		}
		return sb.reverse().toString();
	}

	/**
	 * 十进制 -->二进制
	 * 
	 * @param num
	 * @return
	 */
	public static String toBinary(int num) {
		return trans(num, 1, 1);
	}

	/**
	 * 十进制 -->八进制
	 * 
	 * @param num
	 *            十进制数
	 * @return
	 */
	public static String toEight(int num) {
		return trans(num, 7, 3);
	}

	/**
	 * 十进制 -->十六进制
	 * 
	 * @param num
	 * @return
	 */
	public static String toHex(int num) {
		return trans(num, 15, 4);
	}

}




静态代码快

//格式
static{


}
//特点 
//随着类的加载而执行,只执行一次,用于给类进行初始化的.

class StaticCode{
   static{
     System.out.println("a");
   }

   public static void  show(){
    System.out.println("show run");
  }
}

//例子
class StaticCodeDemo{

     static {
      System.out.println("b");
    }

   public static void main(String[] args){
    
     new  StaticCode();
     new  StaticCode();
     System.out.println("over");  
  }
  
   static {
     System.out.println("c");
    }


}

//输出 为  b c  a  over 


//例子2


class StaticCode{
   int num=0;
  //构造代码块
   {
      System.out.println("e"+this.num);
   }
   //构造方法
    StaticCode(){}
  //构造方法
    StaticCode(int x){
      this.num=9
     System.out.println(this.num);
    }
   //静态代码块 
   static{
      System.out.println("a");
   }

}

class StaticCodeDemo{

     static {
      System.out.println("b");
    }

   public static void main(String[] args){
    
      StaticCode s=null;//    
  }
  
   static {
     System.out.println("c");
    }


}
//只会输出   bc

class StaticCodeDemo{

     static {
      System.out.println("b");
    }

   public static void main(String[] args){
    
       StaticCode  s=new StaticCode();
  }
  
   static {
     System.out.println("c");
    }


}


//输出  b c a  e0 9


//静态代码 和 构造代码块的区别

静态代码: 只有 程序应用到类的数据的时候 ,即 只要类被加载到内存中个 静态代码就会被执行 
构造代码快:主要是在 创建对象的时候  首先被调用 优先于构造函数.



练习


class Fu{
	static{  //静态代码块    只要该类被JVM 加载到内存 就会运行这个 里面的内容 
		System.out.println("fu static run");
	}
	{  //构造代码块  在所有 构造函数前都会运行 ,除非不用构造函数 
		System.out.println("fu gouzao run");
	}
  Fu(){
	  System.out.println("fu run");
  }
  Fu(int x){  //如果不调用该类中的这个构造方法 就不会被运行
	  System.out.println("fu run"+x);
  }
}
class Zi extends Fu{
	static{
		System.out.println("zi static run");
		
	}
	{
		System.out.println("zi gouzao run");
	}
	Zi(){
		//super(); 默认都有  这行
		System.out.println("zi run");
	}
	Zi(int x){
		//super(); 默认都有  这行
		System.out.println("zi run"+x);
	}
	
}
public class day7_T1 {
	public static void main(String[] args) {
			Zi z=new Zi(4);
			
			/*
			fu static run
			zi static run
			fu gouzao run
			fu run
			zi gouzao run
			zi run4
			*/
	}
}



this 和super 的使用

class Person{
	String name;  //默认为0  
	
	 //Perseon(){} 显示写出 默认构造函数 
	
	Person(String name){  //发现 我们没有写 那个默认的构造函数 
		this.name=name;
		System.out.println("fu run"+this.name);
	}
}

class Student extends Person{
	
	Student(){
		super("xx");  //如果没有写父类默认构造函数 ,只能调用 其他构造函数
		System.out.println("zi run");
	}
	
	Student(String name){
		this();  //调用子类自己的  默认构造函数 由于 上面的构造函数 中调用 super("xx") 所以这句话可以了
		//super();  // 发现 写了this()后 这句报错了, 因为  super 要在第一行 
		//this();  //发现 先写 super后 在写 this() 也不行    因为  构造函数中 只能调用一次 父类构造方法 ,而且 super要放在第一行 ,所以这两个不能同时出现
		System.out.println("zi run" +this.name); //如果不调用父类的构造函数 我们就拿不到这个值了.
	}
	
}

public class day7_T2 {
	public static void main(String[] args) {
		Student stu=new Student("aa");
	}

}



//对象的初始化过程

class Person{
 private String name="haha";
 pirvate int age;
 
 Person(){}
 
 Person(String name,int age){
  this.name=name;
  this.age=age;
 }

 {
   this.name="xixi";
   this.age="10";
  }
 

 public static void main(String [] args){

  Person p=new Person(); 

/***这句话做了什么事情

1. 因为 new 用到了Persion.class 所以会先找到Person.class 文件并加载到内存中

2.执行该类中的static  代码快,  如果有的话,给Person.class类进行初始化 

3.在栈内存中 分配存储空间 个p,在堆内存中开辟空间,分配内存地址.

4.然后再在堆内存中建立对象,特有的属性, 并进行默认的初始化

5.然后对属性进行 显示初始化 

6.然后对对象进行构造代码快初始化 

7.对对象进行对应构造函数初始化 

8.将内存地址值复制给栈内存中的变量  p

 */

}
}



对象调用成员的过程

package com.itheima.day6;

public class Person {

	private static String country = "cn";

	private String name;
	private int age;
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	private void speak(){
		System.out.println(this.name+"...."+this.age);
	}

	public static void showCountry(){
		System.out.println("country="+country);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Person p = new Person("xixi",10);
		p.setName("lisi");  //运行有  栈内存的变量会被释放
		
		Person p1 = new Person("xixi",10);
		p1.setName("hah");
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}

}





单例设计模式 GOF (Gang of Four)四人帮

java23种设计模式
//设计模式:解决某一类问题最行之有效的方法

//单例设计模式: 解决一个类在内存中只存在一个对象.

/**
1.为了避免其他程序过多的创建该类对象,先禁止其他程序建立该类对象

2.为了让其他程序可以访问到该类对象,只好 在本类中,自定义一个对象 给其他程序使用,自己控制要创建的对象个数

3.为了方便其他程序使用自定义的该类对象, 可以对外提供一些访问方式

//程序代码的实现

1.将构造函数苏私有化

2. 在类中创建一个本类的对象

3.提供 一个方法可以获取到该对象.

4.该类的一些属性 该怎么样描述的还是 同样的要描述

*/

//类被加载 就初始化了

//称为  :饿汉式  (立即加载) 这个安全点 
class Single{


  private int age;
  private void  setAge(int age){
     this.age=age;
  }
  pirvate int getAge(){
     return  this.age;
  }

  private Single(){}   //私有化后 其他程序就不能创建对象了

  private static Single s=new Single();  //由于 getInstance 中只能使用static 的成员 ,所以只能是  static的了. 由于不能被外界访问 所以只能是 private

 public static Single getInstance(){   //由于 不能创建对象  所有只能是 static  ,由于要被外界访问  所以采用 public 修饰
   return s;
 }

}

class SingleDemo{

  public static void main(String [] args){
     Single s1=Single.getInstance();
      s1.setAge(13);
    Single s2=Single.getInstance();

    System.out.println(s2.getAge);  //13

      
 
  }
}




//单例的第二种方式


//称为 ; 懒汉式  (延迟加载) 效率低
class Single{


  private int age;
  private void  setAge(int age){
     this.age=age;
  }
  pirvate int getAge(){
     return  this.age;
  }

  private Single(){}   //私有化后 其他程序就不能创建对象了

  private static Single s=null;  //由于 getInstance 中只能使用static 的成员 ,所以只能是  static的了. 由于不能被外界访问 所以只能是 private

//注意两个 地方 synchronized 不是同时出现的
 public static /*synchronized*/ Single getInstance(){   //由于 不能创建对象  所有只能是 static  ,由于要被外界访问  所以采用 public 修饰
     if(s==null){
              
           synchronized(Single.class){
              if(s==null)
                s=new Single();
           }
      }
     return s;
 }

}

class SingleDemo{

  public static void main(String [] args){
     Single s1=Single.getInstance();
      s1.setAge(13);
    Single s2=Single.getInstance();

    System.out.println(s2.getAge);  //13

      
 
  }
}

// 只有调用 getInstance 方法后 才被延迟加载.
<think>好的,我现在需要处理用户关于Java枚举类型的问题。用户想了解枚举类型的使用方法和示例。首先,我要回忆一下Java枚举的基本知识,确保自己理解正确。 Java枚举类型是在Java 5引入的,它用于定义一组固定的常量。与传统的常量定义相比,枚举类型更安全、功能更强大。例如,枚举可以有字段、方法,甚至实现接口。这比使用public static final int这样的常量更灵活。 接下来,我需要整理枚举的主要使用方法。用户可能想知道如何声明枚举、如何添加属性和方法、如何在switch语句中使用,以及如何遍历枚举值。这些都是常见的使用场景,应该覆盖到。 然后,示例部分。示例代码要简洁明了,能够展示枚举的不同特性。比如,一个简单的颜色枚举,包含属性的情况,以及带有方法的例子。同时,switch语句的使用也很重要,要展示枚举如何简化代码。 还需要注意用户提供的引用内容。引用[1]提到枚举可以用于表示一组常量、添加属性和方法、实现行为多态和限制输入范围。引用[2]提到了values()方法和遍历枚举值。这些点都需要在回答中体现,并且正确添加引用标识。 在结构上,按照用户的要求,应该分步骤说明使用方法,每个步骤下给出示例代码,并解释代码的作用。最后生成相关问题,帮助用户进一步学习。 现在,检查是否有遗漏。比如,枚举的构造函数是私有的,这一点需要提到吗?是的,因为用户在示例中可能需要了解如何初始化枚举值。另外,values()方法是编译器自动生成的,需要说明清楚。 最后,确保所有数学表达式和公式符合要求,但在这个问题中可能涉及较少。不过,如果有代码块中的符号,需要确认格式正确。例如,代码中的注释和符号是否正确使用。 总结一下,回答的结构应该是: 1. 枚举的基本概念和优点 2. 使用方法分点,每点带示例 3. 引用标识的正确放置 4. 相关问题生成 现在开始组织语言,确保使用中文,清晰易懂,并自然融入引用内容。</think>### Java枚举类型使用方法及示例 #### 一、枚举类型基本概念 Java枚举类型(`enum`)用于定义一组**固定常量**,相比传统常量声明更安全且功能更丰富。枚举可以包含字段、方法、构造方法,甚至实现接口[^1]。 --- #### 二、枚举类型使用方法 ##### 1. 基础声明 **语法**: ```java public enum 枚举名 { 常量1, 常量2, 常量3; } ``` **示例**: ```java public enum Color { RED, GREEN, BLUE; } ``` **使用场景**:表示有限的选项集合,例如状态码、颜色等。 ##### 2. 添加属性和方法 枚举可以定义字段和自定义方法,通过构造方法初始化属性[^1]。 ```java public enum Planet { MERCURY(3.303e+23, 2.4397e6), VENUS(4.869e+24, 6.0518e6); private final double mass; // 质量(kg) private final double radius; // 半径(m) Planet(double mass, double radius) { this.mass = mass; this.radius = radius; } public double surfaceGravity() { return 6.67430e-11 * mass / (radius * radius); } } ``` **调用方式**: ```java double gravity = Planet.MERCURY.surfaceGravity(); ``` ##### 3. 在`switch`中使用 枚举与`switch`结合可提高代码可读性[^1]: ```java public enum Day { MONDAY, TUESDAY, WEDNESDAY } Day day = Day.MONDAY; switch(day) { case MONDAY: System.out.println("工作日开始"); break; case TUESDAY: System.out.println("第二"); break; } ``` ##### 4. 遍历枚举值 使用`values()`方法获取所有枚举值并遍历[^2]: ```java for (Color color : Color.values()) { System.out.println(color); } ``` ##### 5. 实现行为多态 枚举常量可以重写方法,实现不同行为: ```java public enum Operation { ADD { public int apply(int a, int b) { return a + b; } }, SUBTRACT { public int apply(int a, int b) { return a - b; } }; public abstract int apply(int a, int b); } ``` --- #### 三、核心优势 1. **类型安全**:编译时检查非法值。 2. **可扩展性**:支持添加方法和字段。 3. **单例特性**:每个枚举常量然为单例实例。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值