文章目录
一、构造方法
1、构造方法简介
- 构造方法存在的意义:通过构造方法的调用,可以创建对象
1、构造方法:又被称为构造函数/构造器/Constructor
2、构造方法语法结构
[ 修饰符列表 ] 构造方法名(形式参数列表){
构造方法体;
}
3、普通方法语法结构
[ 修饰符列表 ] 返回值类型 方法名(形式参数列表){
方法体;
}
4、对于构造方法来说,返回值类型不需要指定,并且也不能写void
只要写上void,那么这个方法就成为普通方法了
5、对于构造方法来说,构造方法的方法名必须和类名保持一致
2、构造方法调用
-
普通方法这样调用的:方法修饰符当中有static关键字的时候:类名.方法名(是参列表)、方法修饰符列表中没有static的时候:引用.方法名(实参列表)
-
new 构造方法名(实参列表)
-
构造方法返回值:每一个构造方法实际上执行结束之后都有返回值,但是不需要写return;构造方法结束的时候java程序自动返回值。并且返回值类型是构造方法所在类的类型。由于构造方法的返回值类型就是类本身,所以返回值类型不需要缩写。
-
定义一个无参的构造方法:
class User {
public User(){
System.out.println("Constructor");
}
}
public class Test {
public static void main(String[] args) {
//调用User类的构造方法来完成对象的创建
new User();
}
}
-
当一个类显示的将构造方法定义出来了,那么系统则不再默认为这个类提供缺省构造器。建议开发中手动为当前类提供构造方法。
-
构造方法支持重载机制,当在一个类当中编写多个构造方法,则这多个构造方法显然已经构成方法重载机制。
public class User {
//无参构造方法
public User(){
System.out.println("Constructor");
}
//构成了方法重载
public User(String name){
System.out.println("带有String类型的构造器");
}
public User(int i,String name){
System.out.println("1");
}
}
public class Test {
public static void main(String[] args) {
//以下程序创建了4个对象,只要构造方法函数调用,就会创建对象
// 并且一定是在“堆内存”中开辟内存空间
User u1=new User();
User u2=new User(10);
User u3=new User("hello");
User u4=new User(10,"hello");
}
}
构造方法的作用:
- 1、创建对象
- 2、创建对象的同时,初始化实例变量的内存空间(如果是无参的话就赋值为0)
成员变量之实例变量,属于对象级别的变量,这种变量必须先有对象才能有实例变量。
实例变量没有手动赋值的时候,系统默认赋值,那么系统默认赋值是在构造方法开辟执行过程中完成开辟的,即完成初始化的。
3、相关快捷键
在一个类当中元素过多,想要快速查看,在当前的类当中使用Ctrl+O,快捷键,然后输入要查找的元素名称,该名称不一定输入全名称。
ALT+INSERT:能够弹出generate小框,此时就可以快速生成构造方法,或者生成get和set方法。
二、参数传递
java语言当中方法调用的时候涉及到参数传递问题,则参数传递实际上是传递的是变量当中保存的具体的值。只不过有时候这个值是一个字面值,有时候这个值是一个java对象的内存地址。
int i=10;
int j=i;//i传递给j,实际上只是将i变量中保存的10传递给了j,j实际上是一块全新的内存空间。
User u=0x1234;
User u2=u;//u传递给u2,实际上是将0x1234这个值赋给了u2,u和u2实际上是两个不同的局部变量
//但是他们这两个局部变量指向的堆内存中的同一个java对象。
例子一:
由于u当中是数值型变量,因此传递过去的是值,不会改变main方法当中的局部变量
class User11{
//实例变量
int age;
//构造方法(有参)
public User11(int i){
age=i;
}
}
public class Test03 {
public static void main(String[] args) {
int u=10;
add(u);
System.out.println("mian-->"+u);//10
}
public static void add(int u) {
u++;
System.out.println("add-->"+u);//11
}
}
例子二:
由于这里使用的是引用型参数,传递过去的是地址,因此会改变你main函数当中的局部变量
class User0{
//实例变量
int age;
//构造方法(有参)
public User0(int i){
age=i;
}
}
public class Test02 {
public static void main(String[] args) {
User0 u=new User0(20);
add(u);
System.out.println("mian-->"+u.age);//21
}
public static void add(User0 u) {
u.age++;
System.out.println("add-->"+u.age);//21
}
}
三、this关键字
-
1、this是一个关键字,翻译为:这个
-
2、this是一个引用,this是一个变量,this变量中保存了内存地址指向了自身,this存储在JVM堆内存java对象内部
-
3、创建100个java对象,每个对象都有this,也就是有100个不同的this
-
4、this可以出现在实例方法当中,表示this指向当前正在执行这个动作的对象(即this代表当前对象)
-
5、this在多数情况下是可以省略不写的
-
6、this不能使用在带有static的方法中
下图当中的this其实就分别指定是C1和C2:
例:关于顾客购物的行为,由于每个顾客购物的最终结果是不一样的,所以购物这个行为是属于对象级别的。因为每个对象在执行购物这个动作的时候最终结果不同。
- 没有static关键字的方法被称为实例方法,通过引用.访问
- 没有static关键字的变量被称为实例变量
- 当一个行为/动作执行的过程中需要对象参与的,那么这个方法一定要定义为“实例方法”,不能带static关键字
1、调用实例方法和静态方法
public void shopping(){
System.out.println(this.name+"在购物!");
//这里的this就代表当前对象
}
-
static的方法调用不需要对象,直接使用类名,所以执行过程当中没有当前对象,所以不能使用this
-
在static里面不能访问直接访问实例变量和实例方法,因为实例变量和实例方法都需要对象的存在。而static的方法当中是没有this的,即当前对象不存在,自然也就无法访问当前对象的实例变量和实例方法。
//调用实例方法和静态方法
public class Test05 {
public static void main(String[] args) {
//调用doSome这个静态方法
Test05.doSome();
doSome();
//调用doOther这个实例方法,需要创建对象
Test05 t=new Test05();
t.doOther();
//doOther:这里不能直接这样写,会报错,因为main方法没有引用,是static的
}
//静态方法
public static void doSome() {
System.out.println("do Some");
}
//实例方法
public void doOther() {
System.out.println("do Other");
}
//实例方法
public void run(){
//在大括号中的代码执行过程当中一定存在“当前对象”的,也就是一定存在this
//run是实例方法,调用run方法的一定是有对象的
System.out.println("run");
doOther();//不会报错,doOther是一个实例方法,实例方法调用必须有对象的存在
//this在大部分的情况下可以省略
this.doOther();//完整写法
}
}
2、this使用的地方
-
1、可以使用在实例方法当中,代表当前对象【语法格式:this.】
-
2、可以使用在构造方法当中,通过当前的构造方法来调用其他的构造方法【语法格式:this(实参);】
-
重点:this()这种语法只能出现在构造函数的第一行,说明一个构造方法调用其他的构造方法只能出现一次
public class Date {
//属性
private int year;
private int month;
private int day;
//构造函数
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
//当程序员调用无参的构造方法时,默认创建的日期是“1970-1-1”
public Date(){
//以下三段代码可以使用调用有参的构造方法来实现,即在无参的构造方法当中调用有参的构造方法
//但前提是不能创建一个新的对象
/*this.year = 1970;
this.month = 1;
this.day = 1;*/
//new Date(1970,1,1);//这样写是错误的,因为这样做创建了一个新的对象
//这种方式不会创建新的java对象,但同时又可以达到调用其他构造方法的目的。
this(1970,1,1);//并且这个语句只能出现在构造方法当中的第一行
}
//setter and getter
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
//对外提供一个方法将日期输出到控制台
public void print(){
System.out.println(this.year+"年"+this.month+"月"+this.day+"日");
}
}
3、例子
public class Test04 {
//带有static的方法
public static void method1(){
//要求在这里编写程序调用doSome
//使用完整方式调用
Test04.doSome();
//使用省略方式调用
doSome();
//要求在这里编写程序调用doOther
//使用完整方式调用
Tset04 t=new Tset04();
t.doOther();
//使用省略方式调用
//访问i
//采用完整方式访问
System.out.println(t.i);
//采用省略方式访问
}
//不带static的方法
public void method2(){
//要求在这里编写程序调用doSome
//使用完整方式调用
Tset04.doSome();
//使用省略方式调用
doSome();
//要求在这里编写程序调用doOther
//使用完整方式调用
this.doOther();
//使用省略方式调用
doOther();
//访问i
//采用完整方式访问
System.out.println(this.i);
//采用省略方式访问
System.out.println(i);
}
//主方法
public static void main(String[] args) {
//要求在这里编写程序调用method1
//使用完整方式调用
Test04.method1();
//使用省略方式调用
method1();
//要求在这里编写程序调用method2
//使用完整方式调用
Test04 tt=new Test04();
tt.method2();
//使用省略方式调用
}
//没有static方法
int i=10;
//带有static的方法
public void doOther(){
System.out.println("do Other!");
}
//带有static方法
public static void doSome(){
System.out.println("do Some!");
}
}
四、static关键字
1、静态变量
关于java当中的static关键字:
- static表示静态的
- static修饰的方法是静态方法
- static修饰的变量是静态变量
- 所有static修饰的元素都称为静态的,都可以使用类名.的方式访问
- static修饰的所有元素都是类级别的特征,和具体的对象无关
public class Chinese {
String id;
String name;
static String country="中国";
public Chinese(String id,String name){
this.id=id;
this.name=name;
}
}
public class Test01 {
public static void main(String[] args) {
Chinese zhangsan=new Chinese("1","张三");
System.out.println(zhangsan.id+","+zhangsan.name+Chinese.country);
//由于country是静态变量,因此前面使用类名进行引用
Chinese lisi=new Chinese("2","李四");
System.out.println(lisi.id+","+lisi.name+Chinese.country);
//这里不会出现空指针异常,因为country是一个静态的变量
zhangsan=null;
System.out.println(zhangsan.country);
}
}
类似于国籍这样的属性,可以提升为整个模板的特征,那么就可以在变量前面添加static关键字修饰
- 静态变量,在类加载的时候就初始化了,不需要创建对象,内存就开辟了。
- 静态变量存储在方法区内存当中
什么时候成员变量声明为静态变量?
- 当所有对象都有这个属性,并且所有对象的这个属性的值是一样的,则建议定义为静态变量,节省内存的开销。
- 静态变量在类加载的时候初始化,内存在方法区当中开辟,访问的时候不需要创建对象,直接使用类名.变量名即可访问
- 所有静态的数据都可以采用类名,也可以采用引用,但是建议采用类名
- 采用引用.的方式访问静态变量的时候,即使引用是null,也不会出现空指针异常,因为访问静态的数据不需要对象的存在
2、静态代码块
1、语法格式
static{
java语句;
}
2、规则
- 静态代码块在类加载的时候执行,并且只执行一次
- 静态代码块在一个类中可以编写多个,并且遵循自上而下的顺序依次执行
public class Test02 {
static{
System.out.println("类加载1次");
}
static{
System.out.println("类加载2次");
}
static{
System.out.println("类加载3次");
}
public static void main(String[] args) {
System.out.println("main begin");
}
}
3、静态代码块的作用
- 这和具体的需求有关,例如项目中要求在类加载的时候执行代码完成日志的记录。那么这段记录日志的代码就可以编写到静态代码块当中,完成日志记录。
- 静态代码块是java为程序员准备的一个特殊的时刻,被称为类加载时刻。若希望在此刻执行一段特殊的程序,则这段程序可以直接放到静态代码块当中。
- 通常在静态代码块当中完成预备工作,先完成数据的准备工作,例如:初始化连接池,解析配置文件等等。
3、实例代码块
- 1、实例代码块可以编写多个,也是遵循自上而下的顺序依次执行。
- 2、实例代码块在构造方法执行之前之前执行。构造方法执行一次,则实例代码块也执行一次。
- 3、实例代码块也是java为程序员准备的一个特殊的时机,这个特殊的时机被称为:对象初始化时机。
public class Test03 {
//实例代码块
{
System.out.println(1);
}
{
System.out.println(2);
}
public static void main(String[] args) {
System.out.println("main begin");
new Test03();
new Test03();
}
}
4、main方法重载
- 带有static的方法和普通方法一样可以进行重载
public class Test04 {
public static void main(String[] args) {
main(10);
main("你好");
}
public static void main(String args) {
System.out.println(args);
}
public static void main(int args) {
System.out.println(args);
}
}
5、静态方法
方法什么时候定义为静态的方法
- 方法描述的是动作,当所有的对象执行这个动作的时候,最终产生的影响是一样的,那么这个动作已经不再属于某一个对象动作了,可以将这个动作提升为类级别的动作。
- 静态方法当中无法直接访问实例变量和实例方法。
- 大多数等等都定义为实例方法,一般一个行为或者一个动作在发生的时候,都需要对象的参与。但是也有例外:大多数“工具类”中的方法都是静态方法,因为工具类就是方便编程,为了方便方法的调用,不需要new对象。