//static关键字: /*
静态方法的使用注意事项:
1,静态方法不能访问非静态的成员。
但是非静态是可以访问静态成员的。
说明:静态的弊端在于访问出现了局限性。好处是可以直接别类名调用。
2,静态方法中不允许出现this,super关键字。 为什么不行呢?
原理揭秘:
1,静态是随着类的加载就加载了,也是随着类的消失而消失了。
2,静态优先于对象存在,被对象共享。
3,因为静态先存在于内存中,无法访问后来的对象中的数据。所以静态无法访问
非静态,而且内容无法书写this,因为这时对象有可能不存在,this没有任何指向。
*/
class Person
{
private String name;
private int age; Person(String name,int age)
{
this.name = name;
this.age = age;
}
public /*static*/ void speak()
{
System.out.println("name="+this.name+",age="+this.age);
//sleep();
} //定义一个睡觉功能。
public static void sleep()
{
System.out.println(name);
System.out.println("睡觉zzzZZZ");
}
}
class PersonDemo
{
public static void main(String[] args)
{
//Person p = new Person("lisi",20); /*
创建对象就是为了产生实例,并进行数据的封装,
而调用功能时,却没有用到这些对象中封装的数据。
该对象的创建有意义吗?虽然可以编译运行,但是在堆内存中
空间较为浪费。 不建议创建对象。那么该怎么调用呢?java中的解决方案就是static
关键字。
被静态static修饰的方法除了可以被对象调用外,还可以被类名调用。
静态看上去很好,是不是所有的方法都静态呢?不行! 那么什么时候需要将方法定义成静态的呢? 定义功能时,如果功能不需要访问类中定义的成员变量(非静态)时,
该功能就需要定义成static的。
*/ //p.speak();
//p.sleep();
Person.sleep();
}
}
//main函数详解:
/*
静态的主函数:
public static void main(Strng[] args) public:权限最大。
static:不需要对象。直接用给定的类名就可以访问该函数了。
void :不需要返回值。
main :函数名,该名称是固定的。
(String[] args):主函数的参数列表:字符串类型的参数。
args :arguments:参数。该名称就是一个变量名。
*/
class MainDemo
{
public static void main(String[] args)
{
System.out.println(args); //[Ljava.lang.String;@2a139a55
System.out.println(args.length); //
System.out.println(args[0]);
//show();
} public static void show()
{
System.out.println("show run");
}
}
//static_静态变量。
/*
静态变量:
什么时候定义静态变量呢?
当该成员变量的值,每个对象都一致时,就把该成员变量定义成static的。 静态变量和成员变量的区别:
1,所属的范围不同。
静态变量所属与类,成员变量所属与对象。
静态变量也成为类变量;成员变量也称为示例变量。 2,调用不同。
静态变量可以被对象和类调用(一般都用类名调用。)
成员变量只能被对象调用。 3,加载时间不同。
静态变量随着类的加载而加载。
成员变量随着对象的加载而加载。 4,内存存储区不同。
静态变量存储在方法区中。
成员变量存储在堆内存中。
*/
class Circle
{
private double radius; //圆的半径。
private static double pi = 3.14;//每一个圆中都存储一份,浪费内存空间。可以加入静态修饰。 Circle(double radius)
{
this.radius = radius;
} //求圆的面积。
double getArea()
{
return radius*radius*/*Circle.*/pi;
}
}
class CircleDemo
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
//静态加载的内存图解。
class Circle
{
private double radius;
private static double pi = 3.14;
Circle(double radius)
{
this.radius = radius;
}
double getArea()
{
return radius*radius*pi;
}
static void show()
{
System.out.println("circle show run..."+pi);
}
}
class CircleDemo
{
public static void main(String[] args)
{
Circle.show();
}
}
//静态代码块
/*
需求:类一加载,需要做一些动作。不一定需要对象。 //学习目标:必须了解加载的顺序。
静态代码块:
特点:随着类的加载而执行。仅执行一次。
作用:给类进行初始化。
*/ class Demo
{
static int x = 9;//静态变量有两次初始化。一次时默认初始化,一次是显示初始化。
static//静态代码块 .在静态变量显示初始化以后再执行。
{
System.out.println("类加载就执行的部分..."+x);
} static void show()
{
System.out.println("show run.");
}
}
class staticCodeDemo
{
public static void main(String[] args)
{
Demo.show();//堆内存中没有对象。
}
}
/*
构造代码块
*/ class Demo
{
int x = 4;//成员变量 1,默认初始化化,2,显示初始化。
{ //构造代码块。只要创建对象就会被调用。给所有对象初始化,而构造函数只给针对的
//对象初始化。这里面可以定义不同构造函数的共性代码。
System.out.println("code run,,,"+x);
// System.out.println("----->haha");
}
Demo()
{
System.out.println("demo run");
//System.out.println("----->haha");
}
Demo(int x)
{
System.out.println("demo run,,,,"+x);
//System.out.println("----->haha");
}
} class ConstructorCodeDemo
{
public static void main(String[] args)
{
new Demo();//堆内存中有对象。
new Demo(5); int x1 = 6;
{//局部代码块。作用就是:可以控制局部变量的声明周期。
int x = 5;
System.out.println("局部代码块..."+x);
}
System.out.println("over..."+x1);
}
}
//对象的初始化过程。
class Demo
{
static int x = 1;
int y = 1; //静态代码块。
static
{
System.out.println("static code run...x="+x);
} //构造代码块。
{
System.out.println("cons code ...y="+y);
} //构造函数。
Demo()
{
/*
构造函数内的隐式部分。
1,super();//访问父类中的构造函数。
2,成员变量的显示初始化。
3,构造代码块初始化。
*/
System.out.println("cons function ...y="+y);
}
}
class CreateObjectTest
{
public static void main(String[] args)
{
/*
对象创建过程,
1,加载Demo.class文件进方法区,并进行空间分配。
2,如果有静态变量,先默认初始化,再显示初始化。
3,如果有静态代码块,要执行,仅执行一次。
4,通过new在堆内存中开辟空间,并明确首地址。
5,对对象中的属性进行默认初始化。
6,调用对应的构造函数进行初始化。
7,构造函数内部:
构造函数内的隐式部分。
7.1 调用父类的构造函数super();//访问父类中的构造函数。
7.2 成员变量的显示初始化。
7.3 构造代码块初始化。
7.4 构造函数内容自定义内容初始化。、
8,对象初始化完毕后,将地址赋值给d引用变量。
*/
Demo d = new Demo();
}
}
//单例模式 /*
设计模式:解决某一类问题行之有效的解决办法(思想)。
单例(Singleton):设计模式:
学习设计模式必须先弄清楚它是解决什么问题的。 单例模式是解决什么问题的?
可以保证一个类的对象唯一性。 场景:比如多个程序都要使用一个配置文件中的数据,而且要实现
数据共享和交换。必须要将多个数据封装到一个对象中。而且
多个程序操作的是同一个对象。那也就是说必须保证这个配置
文件的唯一性。 怎么能保证对象的唯一性呢?
1,一个类只要提供了构造函数就可以产生多个对象,
完全无法保证唯一。
既然数量不可控,干脆,不让其他程序建立对象。 2,不让其他程序创建对象,对像何在?
干脆,自己在本类中创建一个对象,这样好处是什么,可控!. 3,创建完成后,是不是要给其他程序提供访问的方式。 怎么实现这个步骤呢?
1,怎么就能不让其他程序创建对象呢?
直接私有化构造函数。不让其他程序创建的对象初始化,这样其他程序就
不能创建对象了,但是在卑劣中还是可以创建本类对象的。
2,直接在本类中new一个本类对象。
3,定义一个功能,其他程序可以通过这个功能获取到本类的对象。
*/
//代码体现。 //【调用方法时,对象已经产生了】
//饿汉式。
class Single
{
//私有化构造函数。
private Single(); //2,创建一个本类对象。
private static /*finale*/Single s = new Single();//因为getInstance方法是
//静态的,所以这个方法只能
//访问静态的,所以这里必须
//加静态关键字修饰。
//因为这个对象s是静态的,可以由其他
//程序直接有类名调用,但是这样不安全,
//对象不可控,所以为了不让其他程序直接
//通过类名的方式来调用,加了private
//关键字。 //3,定义一个方法返回这个对象。
public static Single getInstance(int x)
{
//因为这个方法是要返回一个对象,
//就是为了让其他程序获取这个对象的
//所以这个方法的权限要足够大,所以
//为public的。
if(x<0)
return s; } } //单例的延迟加载方式。(单例:单独的对象)【拿到方法的时候,才产生对象】
//懒汉式。
class Single2
{
private static Single2 s2 = null; private Single(){}//私有化构造函数。 public static Single2 getInstance()
{
if(s2==null)
s2 = new Single2();
return s2;
}
} class SingleDemo
{
public static void main(String[] args)
{
//要想获取Single的对象,调用geiInstance方法,
//既然无法通过对象调用,只能用类名调用,那么
//这个方法必须是静态的 Single ss = Single.getInstance();
Single ss2 = Single.getInstance();//ss 和 ss2 指向同一个对象。 //既然对象s也是静态的,干脆就直接用类名调用不就行了?
// Single ss = Single.s;//这种方法是可以实现的,加入
//方法来获取就是为了对象的可控(安全)。
// Single ss2 = Single.s;
}
}
//描述超人。
class SuperMan
{
private String name; private static SuperMan man = new SuperMan("克拉克"); //构造函数私有化。不让其他程序创建本类对象。
private SuperMan(String name)
{
this.name = name;
} //这个方法返回一个本类的对象,给其他程序使用,保证了
//对象的唯一性。
public static SuperMan getInstance()
{
return man;
} public void setName(String name)
{
this.name = name;
} public String getName()
{
return this.name;
} //一般方法。
public void fly()
{
System.out.println(this.name+"...fly");
}
}
class SingleDemo
{
public static void main(String[] args)
{
//超人对象应该是唯一的。保证superMan的唯一性。
//可以使用单例模式解决问题。
//SuperMan man = new SuperMan("克拉克"); SuperMan man1 = SuperMan.getInstance();
SuperMan man2 = SuperMan.getInstance();
man1.setName("英雄");
man2.fly();//输出:英雄...fly 说明man1,和man2指向的是同一个
//对象。
}
}