【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()); }