Java面向对象03

1.static关键字

当在定义类的时候,类中都会有相应的属性和行为。而属性和行为都是通过创建本类对象调用的。当在调用对象的某个行为时,这个行为没有访问到对象的特有数据时,调用方法而创建这个对象有些多余。可是不创建对象,行为又调用不了,这时就会想,那么我们能不能不创建对象,就可以调用行为呢?

class Person
{
    private int age;
    private String name;
    Person(int age ,String name)
    {
        this.age = age;
        this.name = name;
    }
    //说话的行为,说出自己的年龄和姓名
    void speak()
    {
        System.out.println("name="+this.name+",age="+this.age);
    }
    //睡觉行为
    void sleep()
    {
        System.out.println("睡觉ZZZzzz....");
    }
}
class PersonDemo
{
    public static void main(String[] args)
    {
        Person p = new Person(23,"张三");
        p.speak();
        p.sleep();
    }
}

2.静态方法的使用注意事项

静态由来
如果创建对象调用方法,发现这个方法中没有使用到对象中的特有数据,那么创建该对象仅仅是为了调用方法,就显得这个对象创建很多余,这时可以使用static关键字修饰这个方法。
若一个方法被static关键字修饰,则该方法属于类的方法,可以通过类名的方式直接调用。

class Person
{
    private int age;
    private String name;
    Person(int age ,String name)
    {
        this.age = age;
        this.name = name;
    }
    //说话的行为,说出自己的年龄和姓名
    void speak()
    {
        System.out.println("name="+this.name+",age="+this.age);
    }
    //睡觉行为,由于sleep方法没有访问对象的特有数据,可以使用静态修饰
    static void sleep()
    {
        System.out.println("睡觉ZZZzzz....");
    }
}
class PersonDemo
{
    public static void main(String[] args)
    {
        //sleep方法是静态方法,属于类的方法,可以使用类名直接调用
        Person.sleep();
    }
}

什么时候使用静态修饰方法呢?
定义功能时,如果功能不需要访问类中定义的成员变量(非静态)时,该功能就需要静态修饰
静态方法的使用注意事项
通过上面的演示,发现被静态修饰的方法中无法访问非静态的属性和方法。这是为什么呢?

  1. 静态是随着类的加载就加载了。也是随着类的消失而消失了。
  2. 静态优先于对象存在,被对象共享。
  3. 因为静态先存在于内存中无法访问后来的对象的中的数据,所以静态无法访问非静态。而且内部无法书写this。因为这时对象有可能不存在,this没有任何指向。

注意事项
1.静态方法不能访问非静态的成员。但是非静态可以访问静态成员的。
说明:静态的弊端在于访问出现局限性。好处是可以直接被类名调用。
2. 静态方法中不允许出现this,super关键字。
main方法其实也静态的。因为main是程序的入口,是提供给JVM使用的,当在dos中输入java XXX 时,会启动JVM,同时JVM会加载以XXX为名称的这个class文件进内存。并扫描其中有没有main方法。若有main方法JVM就会去调用这个main方法。JVM调用main方法,是不会创建对象的,没有对象怎么调用方法,这个方法只能被静态修饰。JVM通过类名调用的。
既然被静态修饰的方法中无法访问非静态的成员属性和行为,当要静态方法的确需要访问某个成员属性怎么办呢?

3.静态变量

静态不仅可以修饰方法,同时静态也可以修饰成员变量。

class Circle
{
    //圆的半径
    private double radius;
    //圆周率,由于圆周率是固定值,因此所有对象共享这个数据
    //没有必要每个对象中拥有这个数据,因此可以使用静态修饰
    static double pi = 3.14;
    //带参数的构造函数
    Circle(double radius)
    {
        this.radius = radius;
    }
    //获取圆面积
    double getArea()
    {
        return radius * radius * pi;
    }
}
class CircleDemo
{
    public static void main(String[] args)
    {
        System.out.println(new Circle(3).getArea());
    }
}

如果pi这个变量没有被静态修饰的话,当创建Circle对象时,每个对象中都会有pi这个变量,但是pi是个固定不变的值,没有必要每个对象中拥有,这时可以将这个变量静态修饰,让所有对象共享就可以了。

4.静态变量和成员变量的区别

变量所属不同
● 静态变量所属与类,也称为类变量
● 成员变量所属于对象,也称为实例变量(实例变量)
内存中的位置
● 静态变量存储于方法区中的静态区中
● 成员变量存储于堆内存中
在内存中出现的时间
● 静态变量随着类的加载而加载,随着类的消失而消失
● 成员变量随着对象的创建而在堆内存中出现,随着对象的消失而消失
调用方式
● 静态变量可以用类直接调用,也可对象调用
● 成员变量只能被对象调用

5.静态加载的内存图解

public class Person
{
    //人的姓名
    private String name;
    //所有对象都具有国籍属性,并且都会CN,这时可以将这个成员变量定义成静态
的
    private static String country = "CN";
    Person(String name)
    {
        this.name = name;
    }
    void showName()
    {
        System.out.println("name="+name);
    }
    //静态方法
    static void showCountry()
    {
        System.out.println("Country="+country);
    }
}
class StaticDemo
{
    public static void main(String[] args)
    {
        Person p = new Person("欧鹏");
        p.showName();
        //showCountry是静态方法,类名直接调用
        Person.showCountry();
    }
}

在这里插入图片描述

6.代码块

静态代码块
静态代码块,其实就在代码块前面加上了静态关键字,这个代码块就称为静态代码块。
优先于主方法执行,优先于构造代码块执行,不管创建多少对象,静态代码块只执行一次,可用于给静态变量赋值; 用来给类进行初始化.

public class Person {
    private String name;
    private int age;
    static{
        System.out.println("静态代码块执行了");
    }
}

静态代码块的应用场景:类不需要创建对象,但需要初始化,这时可以将部分代码存储到静态代码块中.
构造代码块
直接写在类中的代码块:优先于构造方法执行,构造代码块用于给所有对象初始化用,每创建一次对象就会执行一次构造代码块。构造函数用于给指定对象初始化。

public class Person {
    private String name;
    private int age;
    static{
        System.out.println("静态代码块执行了");
    }  
    {
        System.out.println("构造代码块执行了");
    }
    Person(){
        System.out.println("Person无参数的构造函数执行");
    }
    Person(int age){
        this.age = age;
        System.out.println("Person(age)参数的构造函数执行");
    }
}
class PersonDemo{
    public static void main(String[] args)
    {
        Person p = new Person();
        Person p1 = new Person(23);
    }
}

代码块里变量的作用域:只在自己所在区域(前后的{})内有效
局部代码块
写在局部范围内的代码块。作用:就可以控制局部变量的生命周期。

class Demo
{
    public static void main(String[] args)
    {
        {//局部代码块
            int x = 5;
            System.out.println(" 局部代码块..."+x);
        }
        System.out.println(" over...");
    }
}

7.对象的创建过程

class Demo
{
    static int x = 1; //静态成员变量
    int y = 1;   //非静态成员变量
    static  //静态代码块
    {
        System.out.println("static code...x="+x);
    }
    {//构造代码块
        System.out.println("cons code ...y="+y);
    }
    Demo() //构造函数
    {
        System.out.println("cons function ...y="+y);
    }
}
class CreateObjectTest
{
    public static void main(String[] args)
    {
        Demo d = new Demo();  //创建Demo对象
    }
}

对象加载的流程总结

  1. 加载Demo.class文件进方法区,并进行空间分配。
  2. 如果有静态变量,先默认初始化,显示初始化。
  3. 如果有静态代码块,要执行,仅一次。
  4. 通过new在堆内存中开辟空间,并明确首地址。
  5. 对对象中的属性进行默认初始化。
  6. 调用对应的构造函数进行初始化。
  7. 构造函数内部。
    7.1 调用父类构造函数super();
    7.2 成员变量的显示初始化。
    7.3 构造代码块初始化。
    7.4 构造函数内容自定义内容初始化。
  8. 对象初始化完毕后,将地址赋值给d引用变量。

8.单例模式

设计模式最早来源于建筑领域,是一套被反复使用、多数人知晓的、经过分类、设计经验的总结。使用设计模式是为了可重用、更容易被他人理解、保证可靠性。

设计模式是解决某一种问题的一种思想,是一种行之有效的解决方式。Java中共有23中设计模式。后期会陆陆续续学习这些设计模式。

学习设计模式就是要理解这个模式主要解决什么问题?理解清楚了解决问题,再学习对应的设计模式就简单了。

单例解决的问题:保证一个类的对象在内存中的唯一性,即一个类在内存中的对象有且只有一个。

应用场景:多个程序都在操作同一个配置文件时,需要程序A操作后的结果,程序B要知道,并继续基于程序A操作后的结果进行操作。前提,数据都存储在配置文件对象中,要求程序A和程序B操作的配置文件对象是同一个对象
思路
● 针对上述的应用场景,怎么保证一个类在内存只有一个对象呢?
● 若要保证一个类在内存中对象只有一个,就要限制其他程序不能随便创建这个类的对象。
● 那如何限制其他程序不能创建这个类对象呢?
● 创建对象是要调用构造函数的,那么只要将这个类的构造函数私有了,不让其他程序访问,其他程序就无法创建对象了。但当私有构造函数后,其他程序无法创建对象。
● 但其他程序还要使用这个类对象,那如何获取对像呢?
● 可以在本类中创建自己的对象,对外提供获取本类对象的方法即可。
饿汉模式

public class Single {
        //私有本类中的构造函数
        private Single(){}
        //创建本类对象
        private static Single s = new Single();
        //对外提供获取本来对象方法
        public static Single getInstance(){
                return s;
        }
}

注意问题:
  由于外界无法创建Single对象,没有对象,那就无法调用getInstance方法,这时需要将getInstance方法静态化,这样外界就可以通过类名直接调用该方法。

懒汉模式

public class Single
{
        //私有构造函数
        private Single(){}
        //在本类中创建本类对象
        private static Single instance = null;
        //对外提供静态访问方法,获取本类实例对象
        public static Single getInstance(){
                if(instance == null )  // 这里会有线程安全问题
                {
                        instance = new Single();
                }
                return instance;
        }
}
class SingleDemo
{
        public static void main(String[] args)
        {
                //获取Single类的实例对象s
                Single s = Single.getInstance();
                //获取Single类的实例对象s2
                Single s2 = Single.getInstance();
                System.out.println(s==s2); //true
        }
}

编程练习题

1
在这里插入图片描述

2
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值