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;
}

}



[img]http://dl.iteye.com/upload/attachment/0082/1093/847ad261-51ad-399a-92db-cd729a728952.png[/img]

单例设计模式 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



}
}


[img]http://dl.iteye.com/upload/attachment/0082/1104/5add1fe6-8bc4-3335-91a9-d68f5e98dc17.png[/img]

//单例的第二种方式


//称为 ; 懒汉式 (延迟加载) 效率低
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 方法后 才被延迟加载.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值