【Java构造方法 06】

一、方法重载的条件

1、方法名是相同的

2、方法的参数类型,个数,顺序至少有一个不同

3、方法的返回值类型可以不同,因为方法的重载与返回值类型没有任何关系

4、方法重载只能出现在同一个类里面

5、方法的修饰符可以不同,因为方法的重载与修饰符没有关系

二、构造方法,构造器,构造函数

1、构造方法也是方法

2、构造方法语法:

  [修饰符] 构造方法名(参数列表){

  构造方法体  

}

3、构造方法名必须和类型相同

4、构造方法的作用:

  A、调用构造方法可以创建Java对象,怎么调用呢?使用new关键字调用(注:其他地方的调用,采用“别名.xxx”)

  B、构造方法的执行除了创建Java对象之外,还可以初始化成员变量

5、如果一个类不手动提供任何构造方法,系统会默认提供一个没有参数的构造方法,如果手动提供了,系统则不会再默认创建了

6、构造方法是可以重载的

7、成员变量在构造方法执行的时候才会被初始化

 

注意:构造方法没有返回值类型,并且不能写void

 

package com.company.Course6Exercises;

/**
人类:
属性:私有的  年龄int  性别char

构造方法:
无参,给年龄赋值12 性别赋值为男
有两个参数,初始化年龄和性別

成员方法:
修改年龄
得到年龄
修改性別
得到性别
打印方法,方法名字print,实现打印:年龄是xxx,性别是xxx
*/

class People {
    private int age;
    private char sex;

    //上下两个构造方法的重载
    People(){
        age = 18;
        sex = '男';
    }

    People(int _Age, char _Sex){
        age = _Age;
        sex = _Sex;
    }


    void setAge(int _age){
        age = _age;
    }
    int getAge(){
        return age;
    }

    void setSex(char _sex){
        sex = _sex;
    }
    char getSex(){
        return sex;
    }

    public static void print(){

        //调用无参的构造方法
//        People p = new People();
        //调用有参的构造方法
        People p = new People(20,'男');
        System.out.println("年龄:"+p.getAge()+" 性别:"+p.getSex());
    }
}
package com.company.Course6Exercises;

/**
 * @Created by IntelliJ IDEA.
 * @Author tk
 * @Date 2019/10/9
 * @Time 15:11
 */
public class Person {
    public static void main(String[] args){
        People.print();
    }

}

温习构造方法,成员方法,方法重载,对象的引用

package com.JavaStudy.study0421;

/**  创建动物类
 *   定义一个动物类:
 *   属性:名字,腿
 *
 *   构造方法:
 *   1、无参:给名字赋值xxx,给腿赋值4
 *   2、两个参数,分别给名字和腿赋值
 *
 *   两个成员方法(负载)move方法:
 *   1、无参,打印"xxx在移动"
 *   2、一个参数int n: 打印"n次xxx在移动"
 *
 */
public class Animal {
    String name;
    int leg;

    //方法内的变量是局部变量,局部变量对成员变量进行修改,则必须两者进行关联
    Animal(){
        name="猫";
        leg =4;
    }
    Animal(String _name,int _leg){
        name =_name;
        leg=_leg;
    }

    public void move(){

        System.out.println(name+"在移动");
    }

    public void move(int n){
        System.out.println(n+"次"+name+"在移动");
    }

    public static void main(String[] args){
        Animal a1 = new Animal();
        Animal a2 = new Animal("哈士奇",4);
        a1.move();
        a1.move(4);

        a2.move();
        a2.move(4);
    }
}

封装,属性私有化的例子

package com.JavaStudy.study0421;

/**
 设计一个圆类:要求:
 1、有一个私有的成员变量半径
 2、有一个缺省构造器
 3、有三个成员方法如下:
 第一个方法,能改变圆的半径
 第二个方法,能得到圆的半径
 第三个方法,能计算圆的面积
 */
public class Round {
    private float r;

    Round(){}

    public void setR(float r){
        this.r = r;
    }

    public float getR() {
        return r;
    }

    public float area(float r){
         return (float) (3.14 * r * r);
    }

    public static void main(String[] args){
        Round round = new Round();
        round.setR(2.5f);
        float result = round.area(round.getR());
        System.out.println("圆的面积:"+result);
    }

}

 

三、static的用法(静态代码块)

1、static修饰的数据被称作“静态的”

2、使用static关键字可以定义静态代码块

3、静态代码块在类加载阶段执行,并且只执行一次,是自上而下的顺序依次执行

package com.company.StaticMothod;

/**
 * @Created by IntelliJ IDEA.
 * @Author tk
 * @Date 2019/10/11
 * @Time 10:55
 */
public class StaticMothod {  
    //static静态代码块,在类加载的时候从上而下执行

    static {
        System.out.println("m1");
    }
    static {
        System.out.println("m2");
    }
    static {
        System.out.println("m3");
    }
    public static void main(String[] args){
        System.out.println("验证静态代码块是不是自上而下执行!");
    }
}
====执行结果======
m1
m2
m3
验证静态代码块是不是自上而下执行!

四、实例代码块

1、每调用一次构造方法,则实例代码块就会执行一次

2、实例代码块在构造方法调用之前执行

3、实例代码块也是自上而下的顺序执行

package com.company.StaticMothod;

/**
 * @Created by IntelliJ IDEA.
 * @Author tk
 * @Date 2019/10/11
 * @Time 14:14
 */
public class Instance {

    //实例代码块是在构造方法调用之前执行
    {
        System.out.println("M1");
    }

    Instance(){
        System.out.println("构造方法调用!!!");
    }

    {
        System.out.println("M2");
    }

    {
        System.out.println("M3");
    }



    public static void main(String[] args){
        System.out.println("main begin");

        new Instance();

        new Instance();
    }
}
=======执行结果========
main begin
M1
M2
M3
构造方法调用!!!
M1
M2
M3
构造方法调用!!!

说明:从执行结果看,首先运行主函数的,然后运行实例代码,最后才运行构造方法
由此可以看出实例代码也是从上而下运行的并且在构造方法之前
 

五、所有的static修饰的数据,正规的访问方式是:类名.

static修饰的变量叫做静态变量

static修饰的方法叫做静态方法

什么情况下声明成静态变量?

  所有的对象都有这个特征,并且这个特征所对应的值都是相同的。

  没必要声明成员变量,因为浪费内存

  应该声明成静态变量,在方法去只存储一份没让所有的对象共享这一份数据。

  参数的工具类中的方法都是静态的,目的是方便调用。

package com.company.StaticMothod;

/**
 * @Created by IntelliJ IDEA.
 * @Author tk
 * @Date 2019/10/11
 * @Time 16:28
 */
public class StaticTest {

    //需求:请抽象一个类描述现实世界中的"陆生生物"
    public static void main(String[] args){

        Anamal a1 = new Anamal("熊猫",3);
        Anamal a2 = new Anamal("孔雀",5);

        System.out.println(Anamal.type);
    }
}

class Anamal{
    String name;
    int age;

    static String type="陆生";

    Anamal(String _name,int _age){
        name = _name;
        age = _age;
    }
}

//主要知识点:静态数据,调动通过"类名."

======先声明变量,后面才能调用======

 private static String name = "SUN";
    
    static {
        System.out.println(name);
    }

5.1、所有对象可以共享一个静态数据

package com.JavaStudy.study0421;

/**
 * @Created by IntelliJ IDEA.
 * @Author wufq
 * @Date 2020/4/23 17:10
 * static关键字实现计数器
 */
public class StaticLiZi {

    public static void main(String[] args){

        /*
        为什么会实现static计数:
        1、每调用一次构造方法,就会创建一个对象并且会初始化i=0
        2、d1调用时,构造方法Dog和成员方法print会发生压栈和弹栈动作,弹栈后分配的内存是仍然存在的并且被保存到main方法中,此时i=1
        3、d2调用时,同样会进行压栈和弹栈,静态变量i值在1的基础上被修改为2,依次到d5调用i值就会被叠加被修改。
        4、所以就实现了计数
         */
        Dog d1 = new Dog();
        d1.print();

        Dog d2 = new Dog();
        d2.print();

        Dog d3 = new Dog();
        d3.print();

        Dog d4 = new Dog();
        d4.print();

        Dog d5 = new Dog();
        d5.print();

    }
}

class Dog{
    static int i;

    Dog(){
        i++;
    }

    public void print(){
        System.out.println("一共有"+i+"条狗");
    }
}

六、类内能出现的元素

类{

  成员变量;

  成员方法;

 

  静态变量;

  静态方法;

 

  构造方法

 

  静态代码块;

  实例代码块;

}

 七、static对应的模式:单例模式(堆里面只有一个对象,只有一个堆内存地址)(如果有不同的对内存地址就不是单例模式),不能被继承

1、不是单例模式的例子

package com.JavaStudy.study0421;

/**
 * @Created by IntelliJ IDEA.
 * @Author wufq
 * @Date 2020/4/23 17:54
 * 非单例模式
 */
public class StaticFdiLi {
    public static void main(String[] args){
        User u1 = new User();
        User u2 = new User();

        /*
        分别创建了u1,u2两个对象,两个对象就会对应两个不同的内存地址
         */

        //判断两个对象是不是一个内存地址,执行后发现打印的是false说明就不是一个内存地址,所以不是单例模式
        if(u1 == u2){
            System.out.println("true");
        }else{
            System.out.println("false");
        }
    }
}

class User{
    //缺省构造器
    public User(){}
}


=====执行结果=====
false

 

两种单例模式:饿汉单例模式,懒汉单例模式

1、懒汉式单例模式

package com.company.StaticMothod;

/**
测试User类是否符合单例模式
 单例模式主要解决的问题:保证JVM中该类型Java对象只有一个

 优点:节省内存的开始

 缺点:单例模式中因为构造方法私有化,所以单例模式无法被继承
 因为在子类构造方法中必须使用父类中的构造方法
 */

//懒汉式单例模式
public class DanLi {
    //静态变量
    private static DanLi d;

    /*
    第一步:将所有的构造方法私有化
    目的是:让外部程序不能直接用构造方法创建对象
    因为只要构造方法执行,就会有一个对象诞生
     */

    private DanLi(){}

    //对外提供一个公开获取DanLi类型对象的方法
    public static DanLi getInstance(){
        if(d == null){
            d = new DanLi();
        }
        return d;
    }

}

class T{
    public static void main(String[] args){

        DanLi d1 = DanLi.getInstance();
        DanLi d2 = DanLi.getInstance();

        System.out.println(d1 == d2);
    }
}

=====执行结果=====
true

分析:
1、先声明一个私有变量d,说明堆内会生成一个对象d,值为null
2、DanLi.getInstance():调用getInstance方法时,由于d的初始值已经为nulll,则继续走if判断,创建对象,所以可以继续调动getInstance()对象。

 this和static的例子

静态方法和成员方法有一个区别:

1、如果有成员变量,静态方法想使用成员变量,必须有形式参数,然后把形式参数(局部变量)赋值给成员方法,这样在方法体内才能用的上成员变量

比如:

//成员方法
class Trigon{
    static double bottom; 
    double high;

    Trigon(double high){
        this.high = high;
    }

    //area方法是一个私有的方法,不能被其他类调用,所以需要在本类内用print方法进行调用
    private double area(){ 

        return high*bottom/2;  //成员方法内使用成员变量
    }

    public  void print(){

        System.out.println(this.area());

    }

 

posted @ 2019-10-09 18:10  尘封~~  阅读(191)  评论(0编辑  收藏  举报