文章目录
构造方法
构造方法概述
- 构造方法概述和作用
a. 创建对象,给对象中的成员进行初始化
b. 构造函数(方法) : 我们在创建对象时,除了使用关键字new之外,还有调用构造方法来完成对类的实例化。(创建对象时, Student st = new Student() 感觉像是在调用一个函数,从而猜想应该有一个函数,即:构造函数!) - 构造方法格式特点
a. 方法名与类名相同
b. 没有返回值类型,连void都没有
c. 没有具体的返回值 - 构造方法的一些细节性的描述:
a. 我们自定义的类,默认存在一个空(无)参数的构造方法。(系统将自动提供一个无参构造方法。)
b. 构造方法的语法:方法名与类名相同,没有返回值,也没有void等进行定义返回值类型。
c. 构造函数是必须被调用的,如果构造函数被private修饰,则该类的对象无法进行实例化。
构造函数的方法重载:
- 是什么?
能做很多事,比如定义多个参数类型或个数的构造函数,实例化对象可以传递不同的参数进行实例化,顺便将其成员变量的相应数值就进行设置了! - 特殊:
一个创建出来的类模式有一个无参构造函数的,如果手动给出类的一个有参构造,那么默认无参构造就没有了,如果你还想使用无参构造创建对象,建议你手动写出无参构造,才能进行无参数构造来创建对象(这里也用到了构造函数的重载) - 建议:
a. 永远自己给出无参构造方法
b. 给出有参构造方法(如果需要的话!) - 给成员变量赋值的两种方式
a. setXxx()方法
b. 构造方法 - 示例:
主函数:public class Cat { private String name; private int age; public Cat(){ System.out.println("无参构造调用了"); } public Cat(String name,int age){ System.out.println("有参构造调用了"+name+"==="+age); this.name=name; this.age=age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
public class MyTest { public static void main(String[] args) { Cat cat = new Cat(); //借助set方法给成员变量设置值 cat.setName("汤姆"); cat.setAge(20); System.out.println(cat.getName()); System.out.println(cat.getAge()); System.out.println("-----------------------"); //采用有参构造,给成员变量设置值 Cat cat1 = new Cat("加菲猫", 2); System.out.println(cat1.getName()); System.out.println(cat1.getAge()); } } ------------------------------ 输出: 无参构造调用了 汤姆 20 ----------------------- 有参构造调用了加菲猫===2 加菲猫 2
- 构造方法不用调用到栈中去吗?
- 那如果调用set,get等方法会进栈吗?(理论上来说:一定会!)
- 构造函数前不能加static关键字!(编译器报错!)
创建一个对象的步骤:
- 画图说明一个对象的创建过程做了哪些事情?
Student s = new Student();- 图示:
- 步骤:
(1):加载Student.class文件进内存
(2):在栈内存为s开辟空间
(3):在堆内存为学生对象开辟空间
(4):对学生对象的成员变量进行默认初始化
(5):对学生对象的成员变量进行显示初始化
(6):通过构造方法对学生对象的成员变量赋值
(7):学生对象初始化完毕,把对象地址赋值给s变量
- 案例演示:
a. 定义一个长方形(Rectangle)类,定义求周长(length)和面积(area)的方法,
b. 然后定义一个测试类Test,进行测试。- 代码:
主函数:public class Rectangle { //成员属性 private double width; private double height; //提供无参,有参构造 public Rectangle() { } public Rectangle(double width, double height) { this.width = width; this.height = height; } //提供get set 方法 public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } //提供获取周长的方法 public double getLength() { return (this.width + this.height) * 2; } //提供获取面积的方法 public double getArea() { return height * width; } }
public class MyTest { public static void main(String[] args) { Rectangle rectangle = new Rectangle(); rectangle.setWidth(20); rectangle.setHeight(30); double area = rectangle.getArea(); double length = rectangle.getLength(); System.out.println("面积是:"+area); System.out.println("周长是:"+length); System.out.println("--------------------------"); Rectangle rectangle1 = new Rectangle(60, 30); double area1 = rectangle1.getArea(); double length1 = rectangle1.getLength(); System.out.println("面积是:" + area1); System.out.println("周长是:" + length1); } } ---------------------------- 输出: 面积是:600.0 周长是:100.0 -------------------------- 面积是:1800.0 周长是:180.0
static关键字的引入
- 示例:
主函数:public class Person { public String name; //static 静态的:可以修饰成员变量,成员方法,修饰成员变量,此变量就变成了共享变量 public static String guoji="中国"; }
更改主函数为:public class MyTest { public static void main(String[] args) { //我想并把中国这个 数据,设置成共享数据,让多个对象,去共享这个数据 Person.guoji="英国"; //被静态所修饰的成员,属于类的 推荐使用类名直接调用 //被static所修饰的成员变量,我们称之为类变量 Person p1 = new Person(); p1.name = "张三"; // p1.guoji = "美国"; Person p2 = new Person(); p2.name = "李四"; //p2.guoji = "中国"; Person p3 = new Person(); p3.name = "王五"; // p3.guoji = "中国"; System.out.println(p1.name); System.out.println(p1.guoji); System.out.println(p2.name); System.out.println(p2.guoji); System.out.println(p3.name); System.out.println(p3.guoji); } } -------------------------------- 输出: 张三 英国 李四 英国 王五 英国
public class Test { public static void main(String[] args) { //我想并把中国这个 数据,设置成共享数据,让多个对象,去共享这个数据 Person.guoji = "英国"; //被静态所修饰的成员,属于类的 推荐使用类名直接调用 //被static所修饰的成员变量,我们称之为类变量 Person p1 = new Person(); p1.name = "张三"; p1.guoji = "美国"; Person p2 = new Person(); p2.name = "李四"; p2.guoji = "意大利"; Person p3 = new Person(); p3.name = "王五"; // p3.guoji = "中国"; System.out.println(p1.name); System.out.println(p1.guoji); System.out.println(p2.name); System.out.println(p2.guoji); System.out.println(p3.name); System.out.println(p3.guoji); } } ---------------------------------------------------- 输出: 张三 意大利 李四 意大利 王五 意大利
- 结论: 由此我们得到了一个结论,属于类变量的变量其实内存是在代码区的。当这个类被引入的时候就已经存在于内存了(尽管此时还未经历初始化),堆内存中的对象其中的某个成员变量(现在叫做类变量)都是指向这个代码区的内存的。所以:类变量的所有该类对象所共有的,一旦一个对象对其操作,就相当于改变了代码区中该变量的数值,因为其他该类对象也指向这里,所以其他对象该变量的数值也都发生了变化。
- 画图演示: 带有static的内存图(待补充!)
- static关键字的特点:
a. 随着类的加载而加载
b. 优先于对象存在
c. 被类的所有对象共享
实这个特点也是在告诉我们什么时候使用静态?
如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。
举例:
饮水机(用静态修饰)
水杯(不能用静态修饰)
d. 可以通过类名调用
其实它本身也可以通过对象名调用。
推荐使用类名调用。
静态修饰的内容一般我们称其为:与类相关的,类成员 - static的注意事项:
a. 在静态方法中是没有this关键字的
如何理解呢?
静态是随着类的加载而加载,this是随着对象的创建而存在。
静态比对象先存在。
b. 静态方法只能访问静态的成员变量和静态的成员方法
简单记:静态只能访问静态,非静态可以访问静态的也可以访问非静态的
static 小结
- static 静态的:可以修饰成员变量,成员方法,修饰成员变量,这个成员变量就是共享的了。(放在了常量池中?即:静态修饰后的变量在代码区就已经生成了并且完成了赋值)
- 被静态修所修饰的成员,属于类的 推荐使用类名直接调用
- 被static所修饰的成员,已经变成了类变量,在类被加载的时候,就已经完成类初始化
- 实例变量被实例(对象)调用,类变量推荐使用类进行直接调用(不推荐使用对象进行调用)
- static 不仅可以修饰成员变量还可以修饰成员方法。
- static 修饰过后的成员变量或者方法,都不用需要对象来调用,直接用类名调用就OK了,而且不需要对类进行实例化。
- 加载时机的问题(static 修饰的方法随着类加载就已经加载了,所以在static修饰的方法中不能用类的成员变量,但可以用类变量,因为此时类的成员变量还不存在,new了对象以后类成员变量才存在,所以类加载时需要将static修饰的方法加载到方法区中的静态区,此时static修饰的方法中不允许存在类的成员变量)
- 静态只能调用静态,非静态既能调用静态也能调用非静态
- 在非静态方法中不能使用this
- 经典例题:(重点理解!)
public class Test { static int total = 10; public static void main(String[] args) { new Test(); new Test(); } public Test() { int temp = this.total; if (temp++ > 5) { this.total += temp; System.out.println(temp); } } } -------------------------------- 输出: 11 22
静态变量和成员变量的区别:
- 所属不同
a. 静态变量属于类,所以也称为类变量
b. 成员变量属于对象,所以也称为实例变量(对象变量) - 内存中位置不同
a. 静态变量存储于方法区的静态区
b. 成员变量存储于堆内存 - 内存出现时间不同
a. 静态变量随着类的加载而加载,随着类的消失而消失
b. 成员变量随着对象的创建而存在,随着对象的消失而消失 - 调用不同
a. 静态变量可以通过类名调用,也可以通过对象调用,推荐使用类名调用
b. 成员变量只能通过对象名调用
JDK提供的帮助文档
如何使用JDK提供的帮助文档?
A. 找到文档,打开文档
B. 点击显示,找到索引,出现输入框
C. 你应该知道你找谁?举例:Scanner
D. 看这个类的结构(需不需要导包)
- java.lang包下的内容不需要我们手动导入
- 其它包下的内容需要我们手动导入
- 文档中的对应内容:
名称 | 对应内容 |
---|---|
类 | API文档 |
成员变量 | 字段摘要 |
构造方法 | 构造方法摘要 |
成员方法 | 方法摘要 |
E. 看这个类的说明(简单的了解一下)
F. 看开始版本
G. 看构造方法
H. 看成员方法
- 看左边:
是否是static的,如果是我们就不需要创建对象,直接可以使用类名调用该方法;看返回值类型,返回值是什么类型,我就使用什么类型声明的变量来接收。 - 看右边:
看参数列表: 参数的个数 , 参数的类型 ; 它需要什么参数使用的时候,就传递什么参数即可。
i. 然后使用
JDK帮助文档使用实践:学习Math类的随机数功能
- Math类概述:
类包含用于执行基本数学运算的方法 - Math类特点:
a. 由于Math类在java.lang包下,所以不需要导包。
b. 没有构造方法,因为它的成员全部是静态的。 - 获取随机数的方法:
public static double random() 返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。 - 我要获取一个1-100之间的随机数,肿么办?
int number = (int)(Math.random()*100)+1
使用math进行一次猜数游戏:
- 示例:
public class Test{ public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int num = (int)(Math.random()*100+1); System.out.println("请你输入一个 0~100 之间的数字:"); int input_num = scanner.nextInt(); int count = 9; while (count >= 0){ if (input_num > num){ System.out.println("您输入的数字偏大了!您的剩余机会还有"+count--); }else if (input_num < num){ System.out.println("您输入的数字偏小了!您的剩余机会还有"+count--); }else { System.out.println("您猜测对了!总共使用了"+(10-count)+"次机会"); break; } System.out.println("请你输入一个 0~100 之间的数字:"); input_num = scanner.nextInt(); } if(count<0){ System.out.println("您的猜测机会已经用完了!"); } } } ------------------ 输出: 请你输入一个 0~100 之间的数字: 50 您输入的数字偏大了!您的剩余机会还有9 请你输入一个 0~100 之间的数字: 25 您输入的数字偏大了!您的剩余机会还有8 请你输入一个 0~100 之间的数字: 13 您输入的数字偏大了!您的剩余机会还有7 请你输入一个 0~100 之间的数字: 6 您输入的数字偏小了!您的剩余机会还有6 请你输入一个 0~100 之间的数字: 10 您输入的数字偏小了!您的剩余机会还有5 请你输入一个 0~100 之间的数字: 12 您输入的数字偏大了!您的剩余机会还有4 请你输入一个 0~100 之间的数字: 11 您猜测对了!总共使用了7次机会
代码块
- 代码块概述:
在Java中,使用{}括起来的代码被称为代码块。 - 代码块分类:
根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)。 - 常见代码块的应用:
a. 局部代码块
在方法中出现;限定变量生命周期,及早释放,提高内存利用率
b. 构造代码块
在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
c. 静态代码块 (注意静态只能调用静态!)
在类中方法外出现,并加上static修饰;用于给类进行初始化,在类加载的时候就执行,并且只执行一次。 - 看程序写结果(经典例题)
class Student { static { System.out.println("Student 静态代码块"); //3 } { System.out.println("Student 构造代码块"); //4 6 } public Student() { System.out.println("Student 构造方法"); //5 7 } } class StudentDemo { static { System.out.println("StudentDemo的静态代码块"); //1 } public static void main(String[] args) { System.out.println("我是main方法"); //2 Student s1 = new Student(); Student s2 = new Student(); } } ---------------------------- 输出: StudentDemo的静态代码块 我是main方法 Student 静态代码块 Student 构造代码块 Student 构造方法 Student 构造代码块 Student 构造方法
转载:https://blog.csdn.net/weixin_35995730/article/details/102486446
查看评论