静态修饰的特点:
static是一个修饰符,用于修饰成员(成员变量和成员函数)。
1,静态成员随着类的加载而加载。
2,静态成员优先于对象存在。
3,静态成员被所有对象所共享
4,静态成员中多了一个调用方式,可以被类名直接调用。
静态使用的注意事项。
1,静态方法只能访问静态成员。
非静态方法既可以访问静态又可以访问非静态。
2,静态方法中不可以定义this,super关键字。
因为this代表是对象。而静态存在时,有可能没有对象。所以静态方法运行时,this是没有任何对象代表的。
简单说,先进内存的数据不可以访问后进内存的数据,可是后进内存数据可以访问先进内存的数据。
3,主函数是静态的。
静态:
好处:静态成员多了一种调用方式。可以直接被类名调用
格式 :类名.静态成员。也可以被对象调用。
弊端:静态方法只能访问静态成员,出现了访问局限性。
静态修饰的数据对象共享的数据,存放在方法区的静态区中。
非静态的数据,是每一个对象特有数据。存放在对象的所属的堆内存中。
例子1:静态修饰符static的用法实例。
- package cn.itheima.day18;
- class Person{
- String name;
- static String country = "CN";
- public static void show(){
- System.out.println("country="+country);
- }
- }
- public class StaticDemo {
- public static void main(String[] args) {
-
- Person.show();
- Person p = new Person();
- p.name="zhangsan";
- System.out.println(p.name);
- Person p2 = new Person();
- p2.name="lisi";
- System.out.println(p2.name);
- }
- }
当成员变量被静态修饰后。
静态成员变量和非静态成员变量的区别:
1,静态变量也称为类变量,也就是直接可以被类名调用的变量。这个变量是所属于类的。
非静态变量成为成员变量,或者实例变量,是被对象调用的,是所属具体对象的。
2,静态变量随着类的加载而加载,也意味着随着类的消失而消失。生命周期最长。
实例变量,随着对象的创建而加载,随着对象的消失而消失。按照对象的生命周期而存在。
3,静态变量存储在方法区的静态区中。
实例变量存在于对象所属的堆内存中。
4,静态变量数据,被所有对象所共享。
实例变量是对象中的特有数据。
任何成员被访问使用,必须要被调用。如果是非静态成员,必须要被对象调用。在本类中调用是使用的是this。如果是静态成员,必须要被类名调用。只不过在书写时,可以省略。静态变量在静态区中也会进行默认初始化。
例子2:静态成员的调用方式。
- package cn.itheima.day18;
- class Demo{
- int num1 = 3;
- static int num2 = 5;
- void show(){
- System.out.println("num1="+this.num1);
- System.out.println("num2="+Demo.num2);
- }
- static void method(){
- System.out.println("num2="+Demo.num2);
- }
- }
- public class StaticDemo2 {
- public static void main(String[] args) {
- Demo d = new Demo();
- d.show();
- d.method();
- System.out.println("------------");
- Demo.method();
- }
- }
什么时候使用static呢?
成员变量:
什么时候被静态修饰呢?
当该成员变量所存储的数据,每一个对象都是一样的,这时没有必要把该数据存储到每一个对象中,只要让所有对象共享该数据即可,这时成员就需要被static修饰。
当数据需要被对象共享时,就使用static修饰。这样可以对共享的数据节约内存。
成员函数:
当成员函数内并没有访问对象中的特有数据时,就将该方法定义成静态的。
简单说:该函数如果访问了成员变量,该函数就是非静态的。
该函数没有访问过成员变量,或者访问过静态的成员变量,那么为了程序的严谨性,将该方法定义成静态的。因为该方法不需要对象存在,既可以使用。
例子3:定义静态成员函数的实例演示。
- package cn.itheima.day18;
- class Person1{
- String name;
- static String country = "CN";
- Person1(String name){
- this.name = name;
- }
- public void show(){
- System.out.println("name="+this.name);
- }
- public static void method(){
- System.out.println("country="+Person1.country);
- }
- }
- public class StaticDemo3 {
- public static void main(String[] args) {
- Person1 p1 = new Person1("aa");
- p1.show();
- Person1 p2= new Person1("bb");
- p2.show();
- Person1.method();
- }
- }
例子4:静态函数的实例演示。
- package cn.itheima.day18;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public class ArrayTool {
- private ArrayTool(){}
-
- public static void sort(int[] arr){
- for(int x = 0;x<arr.length-1;x++){
- for(int y = x+1;y<arr.length;y++){
- if(arr[x]>arr[y]){
- swap(arr,x,y);
- }
- }
- }
- }
-
- private static void swap(int[] arr, int x, int y) {
- int temp = arr[x];
- arr[x] = arr[y];
- arr[y]=temp;
- }
-
- public static String arrToString(int[] arr){
- String str="[";
- for(int x = 0;x<arr.length;x++){
- if(x!=arr.length-1){
- str=str+arr[x]+",";
- }else {
- str = str+arr[x]+"]";
- }
- }
- return str;
- }
-
- public static int getMax(int[] arr){
- int max=0;
- for(int x = 1;x<arr.length;x++){
- if(arr[x]>arr[max]){
- max =x;
- }
- }
- return arr[max];
- }
- }
- ---------------------------------
- package cn.itheima.day18;
- public class ArrayToolDemo {
- public static void main(String[] args) {
- int[] arr = {3,1,4,5};
- String str1 = ArrayTool.arrToString(arr);
- System.out.println(str1);
- ArrayTool.sort(arr);
- String str = ArrayTool.arrToString(arr);
- System.out.println(str);
- }
- }
主函数静态的,说明主函数只能直接访问静态的成员。
public static void main(String[] args)
public: jvm调用的函数必须权限足够大。所以被public修饰。
static: 主函数随着类的加载而加载,jvm不需要创建该类对象既可以完成对该函数的调用,所以是静态的。
void: 主函数没有返回值。
main: 函数名,是固定的,jvm认识。
(String[]args):主函数的参数列表,参数类型是:一个字符串数组类型的参数。
args:参数名称。
主函数有参数,那么jvm调用的时候,就需要传入相对应的实际参数。
问:jvm调用主函数时,到底传入了什么呢?
//System.out.println(args);//[Ljava.lang.String;@de6ced
//[Ljava.lang.String;@de6ced:通过这个结果看到,args指向了一个具体的数组实体。
//而且该数组中的元素是String类型的。
System.out.println(args.length);//0
//通过两个输出语句,就可以验证,jvm给主函数传递的实际参数是: new String[0];
这是jvm传入的默认值。但是没什么用,所以我们在使用main时,可以自定义该主函数数组中的元素。
例子5:主函数分析的实例演示。
- package cn.itheima.day18;
- public class MainDemo {
- int x = 4;
- public static void main(String[] args) {
-
-
-
-
- System.out.println(args.length);
-
-
-
-
-
- String arr[]={"haha","hehe","heihei","xixi"};
- new MainDemo().show();
- Test.main(arr);
- }
- public void show(){
- System.out.println("x="+x);
- }
- }
- class Test{
- public static void main(String[] args){
- for(int a=0;a<args.length;a++){
- System.out.println(args[a]);
- }
- }
- }
静态代码块。
格式:
static{
code..;
}
作用:当类在加载进内存时,如果需要进行一些内容的执行,完成一个类的初始化。就需要使用静态代码块来完成,给类进行初始化。
执行特点:当类被加载时,静态代码就执行了,而且只执行一次。而且优先于main函数执行。
例子6:静态代码块的实例演示。
- package cn.itheima.day18;
-
- class StaticCode{
- {
- System.out.println("AAAAA");
- }
- static{
- System.out.println("a");
- }
- public StaticCode() {
- System.out.println("StaticCode");
- }
- static void show(){
- System.out.println("show run");
- }
- }
- public class StaticCodeDemo {
- static {
- System.out.println("b");
- }
- public static void main(String[] args) {
- System.out.println("d");
-
- new StaticCode();
- System.out.println("e");
- }
- static{
- System.out.println("c");
- }
- }
-
-
-
-
设计模式:就是解决某类问题最行之有效的解决方案,设计模式是一种思想。
java中总结出来23种设计模式。
单例设计模式(23种设计模式之一):
解决的问题:保证一个类在内存中的只存在一个对象。
简单说:保证一类在内存中的对象唯一性。
应用场景:比如配置文件。A要使用配置文件对象。B程序也要使用配置文件对象。希望A程序对配置数据修改后,B程序可以直接使用,那么就需要A程序,和B程序使用的同一个对象.
如何保证一个类在内存中的对象唯一性呢?
1)为了控制该类的对象建立,不让其他程序建立该类的对象。
2)在本类中自定义一个本类对象。
3)对外提供获取该对象的方式即可。
代码如何实现呢?
1)可以将构造函数私有化。这样对方程序创建就无法初始化。已达到不允许,其他程序创建对象的目的。
2)在本类中,通过new创建一个本类对象。
3)提供一个公共的方法返回该对象,方便于其他程序获取该对象。
代码体现具体:
1)私有化构造函数。
2)创建一个私有并静态的本类的对象。
3)创建一个公共的static方法返回该对象。
例子7:单例模式的实例演示。
- package cn.itheima.day18;
-
- class Single{
- private static Single s = new Single();
- private Single(){}
- public static Single getInstance(){
- return s;
- }
- }
-
- class Demo3{
- private int num = 4;
- private static Demo3 d = new Demo3();
- private Demo3(){}
- public static Demo3 getInstance(){
- return d;
- }
- public int getNum() {
- return num;
- }
- public void setNum(int num) {
- this.num = num;
- }
- }
- public class SingleDemo {
- public static void main(String[] args) {
-
-
-
- Demo3 d1 = Demo3.getInstance();
- Demo3 d2 = Demo3.getInstance();
- d1.setNum(10);
- d2.setNum(20);
- System.out.println("d1.num="+d1.getNum());
- System.out.println("d2.num="+d2.getNum());
- }
- }
对象的延迟加载方式。这种方式看上去很美,但是当并发访问getInstance方法时,容易出现安全隐患(线程安全问题)
懒汉式
例子8:单例设计模式(懒汉式)的实例演示。
- package cn.itheima.day18;
-
- class Single1{
- private static Single1 s = null;
- private Single1(){}
- public static Single1 getInstance(){
- if(s==null){
- s = new Single1();
- }
- return s;
- }
- }
- public class SingleDemo1 {
- public static void main(String[] args) {
- Single1 ss = Single1.getInstance();
- Single1 ss1 = Single1.getInstance();
- System.out.println(ss==ss1);
- }
- }
使用时,一般使用饿汉式。
而面试时,都面试懒汉式,因为涉及的技术细节很多。
面向常见问法:请写出一个单例延迟加载的示例。这个考的就是懒汉式.