1构造方法

一个Person类,属性都被private了,外界无法直接访问属性,必须对外提供相应的set和get方法。但如果需要在创建对象的同时明确对象的属性值,就需要构造方法了。

1.1定义

构建创造时用的方法,即就是对象创建时要执行的方法

格式:

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

  {

  }

1.2特点

1)构造方法没有返回值类型。也不需要写返回值。因为它是为构建对象的,对象创建完,方法就执行结束。

2)构造方法没有具体的返回值。

3)构造方法名称必须和类名保持一致。

这就可以解释了,创建对象时,要加一个扩号,这不就是在调用方法嘛,

Person p=new Person();

例:

public class Person {
private String name;
private int age; public Person(String name, int age) {
super();
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 Test {
public static void main(String[] args) {
Person p2=new Person("张三",18);
System.out.println(p2.getName());
System.out.println(p2.getAge());
}
}

1.3内存图

步骤解释:

1 main方法进栈

2在堆中开内存,赋初值

3有参构造方法进栈

4传参,赋值

5有参构造弹栈

6地址赋值给p2

7 getname进栈,通过地址找到name,打印

8 getage进栈,通过地址找到age,打印

1.4默认构造方法

编译器在编译java文件时,如果发现类中没有构造方法,会自动添加一个空参构造。

但如果类中只要有一个构造方法,则不会自动添加空参构造了。

如果写了有参构造方法,那么new对象时,再用空参的就会报错。

所以如果写了有参构造,最好把空参构造也加上。因为使用空参构造的情况更多。有参构造用的比较少,一般测试时用。

当描述的事物在创建其对象时就要明确属性的值,就用有参的

若创建对象时不需要明确具体的数据,可以不用写构造方法,因为会自动加默认的空参构造方法。

还是上面的例子,因为Person定义了有参,所以test再调用空参就会报错:

1.5注意的细节

1)一个类中可以有多个构造方法,(空参、部分成员变量是参数、全部成员变量都是参数)这其实是方法重载。

2)构造方法可以被private修饰,这样其他程序无法创建该类的对象了。

如果类比较重要,就可以这样,构造方法用private修饰,不让创建对象。

其他方法可以用static修饰,那么就可以直接用类.方法,这样调用了。

例如System类,就是这样的,

在eclipse中,在类上面,ctrl+点击该类,可以查看源码:

1.6构造方法和一般方法区别

构造方法在对象创建时就执行了,而且只执行一次。

一般方法是在对象创建后,需要使用时才被对象调用,并可以被多次调用。

对象在创建之后需要修改和访问相应的属性值时,在这时只能通过set..或者get..方法来操作。

所以构造方法可以不写,get set必须写

例:

class Person {
void Person() {
}
}
class PersonDemo {
public static void main(String[] args) {
Person p = new Person();
}
}

这段代码的Person前面有返回值,所以不是构造方法,那么就会自动添加一个空参构造。所以代码是可以运行的,可以new对象的。但是不建议这样写,可以看到在eclipse中出现警告:

2 this关键字

之前用this可以解决成员变量和局部变量同名的问题。

this代表的是对象,哪个对象调用了this所在的方法,this就代表哪个对象。

this还可以用于在本类中构造方法之间的调用。

2.1格式:

  this(参数列表);

注意:只能构造方法里用this(),普通方法里不能用this()。

例:

public class Person {
private String name;
private int age; public Person(){
//调用本类构造方法
this("李小华",19);
} public Person(String name,int 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 Test {
public static void main(String[] args) {
Person p1=new Person();
System.out.println(p1.getName());
System.out.println(p1.getAge()); Person p2=new Person("张小美",18);
System.out.println(p2.getName());
System.out.println(p2.getAge());
}
}

这里的this("李小华",19);

相当于:

但是,this必须写在第一行,如果这样,是不行的

原因是初始化动作要最先执行。

2.2内存图

步骤解释:

1main进栈,看到new,堆中开内存,属性赋初值

2空参进栈

3找第一个参数是name,age的构造方法,进栈,并把参数传过去

4赋值

5有参构造弹栈,空参构造弹栈

6地址赋给p

7getName进栈,打印,getAge进栈,打印

例:判断两个人是否是同龄人

(之前代码)

3 super关键字

3.1可以用于子父类中构造方法的调用

例:

public class Person {
public Person(){
System.out.println("这是父类构造方法");
}
}
public class Student extends Person{
public Student(){
System.out.println("这是子类构造方法");
}
}
public class Test {
public static void main(String[] args) {
Student s=new Student();
}
}

为什么会这样呢?因为在创建子类对象时,父类的构造方法会先执行,

子类中所有构造方法的第一行有默认的隐式super();语句。

格式:

  调用本类中的构造方法

  this(实参列表);

  调用父类中的空参数构造方法

  super();

  调用父类中的有参数构造方法

  super(实参列表);

3.2 但是,如果父类定义了有参构造,那么子类则必须调用super(参数),必须手动写上。

因为父类不会自动创建空参构造了,所以子类的super()就找不到了。

public class Person {
public Person(String name){
System.out.println("这是父类构造方法");
}
}

改成这样就可以了:

所以一个类只要定义了有参构造,一定再写一个空参构造,因为有可能被继承,不写会导致子类报错。

3.3为什么子类对象创建都要访问父类中的构造方法

例:

public class Person {
int a=1;
public Person(String name){
a=5;
System.out.println("这是父类构造方法");
}
}
public class Student extends Person{
public Student(){
super("张三");
System.out.println("这是子类构造方法");
}
}
public class Test {
public static void main(String[] args) {
Student s=new Student();
System.out.println(s.a);
}
}

这里Student是Person的子类,因为Person中在构造方法改变了成员变量的值,所以如果Student不访问Person的构造方法,那么就得不到Person中真正的成员变量的值了,也就不是真的继承了。

总结:

子类会继承父类中的内容,所以子类在初始化时,必须先到父类中去执行父类的初始化动作。这样,才可以使用父类中的内容。

子父类是会一级一级的调用的,最终是object。

3.4如果有this()

如果子类的构造方法第一行写了this调用了本类其他构造方法,那么super调用父类的语句就没有了。因为this()或者super(),只能定义在构造方法的第一行,因为初始化动作要先执行。

例:

public class Animal {
public Animal(int age){
}
}

这里写了this(),那么意思就是调用的下面的那个有参构造,而这里面有super,所以,上面就不能再写super了,会报错。

3.5总结:

1)如果有this();那么就不会有super();了。不写也不会自动加了。

2)构造方法只要直接或间接可以调用父类构造方法就可以。

3)this和super都是只能在构造方法中使用

在eclipse中也可以有构造方法的快捷方式:

右键--source--Generate Constructor using Fields

可以点任意个,一个不选,就是空参构造。

可以看到,点出来后,第一行就是super();

3.6 super练习

描述学生和工人这两个类,将他们的共性name和age抽取出来存放在父类中,并提供相应的get和set方法,同时需要在创建学生和工人对象就必须明确姓名和年龄。

public class Person {
private String name;
private int age; public Person(String name, int age) {
super();
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 Student extends Person{
public Student(String name, int age) {
super(name, age);
}
}
public class Worker extends Person{
public Worker(String name, int age) {
super(name, age);
}
}
public class Test {
public static void main(String[] args) {
Student s=new Student("小红帽",18);
System.out.println(s.getName());
System.out.println(s.getAge()); Worker w=new Worker("大灰",81);
System.out.println(w.getName());
System.out.println(w.getAge());
}
}

super通常是这么用的,父类的构造方法既可以给自己的对象初始化,也可以给自己的子类对象初始化。

总结:

this的三个作用:

  解决成员变量和局部变量同名问题

  代表本类对象,调用本类中的变量和方法

  构造方法之间的调用

super的两个作用:

  代表父类对象,调用父类的变量和方法

  子父类中构造方法的调用

4 final关键字

有些类在描述完之后,不想被继承,或者有些类中的部分方法功能是固定的,不想让子类重写。这时需要使用关键字final,final的意思为最终,不可变。final是个修饰符,可以用来修饰类,类的成员,以及局部变量。不能修饰构造方法

4.1 final修饰类

final修饰类不可以被继承,但是可以继承其他类(也叫太监类)

例:

public class Person {
} public final class Father extends Person{
}

这里的father就不能被继承了。

4.2 final修饰方法

final修饰的方法不可以被子类重写,但父类中没有被final修饰方法,子类重写后可以加final。(也叫太监方法)

例:

public final class Father{
public final void method1(){
}
public void method2(){
}
}
public class Son extends Father{
public final void method2(){
}
}

这里son可以重写method2,不能重写method1

4.3 Final修饰局部变量

1)局部变量是基本数据类型(称为常量):一旦赋值,终身不变

2)局部变量是引用数据类型:一旦赋值一个地址,终身不变。但是地址内的对象属性值可以修改。

4.4 Final修饰成员变量

必须手动赋值或构造方法赋值。因为成员变量有默认值null,不赋值就终身是null了。

只要在分配地址之前(也就是创建对象之前)赋值就可以。

例:

这样才可以:

或这样:

public class Person {
final String name2;
public Person(String name2){
this.name2=name2;
}
}

5 static关键字

被static修饰的成员变量属于类,不属于这个类的某个对象。

被static修饰后就共享了(有一个改变,就全变了)。

5.1例:

public class Student {
private String name;
private String schoolname; public Student() { } public Student(String name, String schoolname) {
this.name = name;
this.schoolname = schoolname;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getSchoolname() {
return schoolname;
} public void setSchoolname(String schoolname) {
this.schoolname = schoolname;
}
}
public class Test {
public static void main(String[] args) {
Student s1=new Student("小红","清华大学");
Student s2=new Student("小明","清华大学");
Student s3=new Student("小亮","清华大学");
s2.setSchoolname("北京大学"); System.out.println(s1.getSchoolname());
System.out.println(s2.getSchoolname());
System.out.println(s3.getSchoolname());
}
}

说明schoolname是属于每一个对象的

改:private static String schoolname;

这时schoolname是共享的了,是属于Student类的了。

5.2内存图

(数据共享区也叫 静态区)

内存图步骤说明:

1 test.class进共享区,扫描到main,student.class,也进入

2因为main是static,所以main进静态区

3扫描student.class,有static的schoolname,就进静态区,并赋值初始值null

4 main方法进栈

5 有new,就在堆中开内存,找到属性 name赋值null(这时不会再找schoolname了,因为已经在静态区了)

6 分配地址

7 构造方法进栈,传值:小红,清华大学

8 this.name,找到地址,然后找到name,赋值小红

9 根据地址去静态区找schoolname(这里应该用类.变量才对,但是用对象.变量还是能找到的)静态区的schoolname被改值为清华大学

10构造方法弹栈

11 地址赋值给s1

12 s2的new,s3的new,过程是一样的...

13 执行到s2.setSchoolname("北京大学")这一步时,静态区schoolname被改成北京大学

14 后面System.out.println访问的就全是北京大学了

5.3 Static特点

1)属于类,不属于对象

如果一个对象将static成员变量值进行了修改,其他对象的也跟着变,就是共享一个。

2)通过类名直接调用,不建议用对象调用(会有警告)

这样就可以:

5.4注意的地方

1)不能用this和super调用(因为this代表本类对象,super代表父类对象,但是被static后已经不属于对象了)

2)静态内容是优先于对象存在,只能访问静态

3)同一个类中,静态成员只能访问静态成员,不能访问非静态

简单记:

非静态可以调静态

静态不能调非静态

因为static是进共享区的,所以可以理解为先有static show2,后有age,所以在show2中找不到age。

这也解释了,一个类中有main方法时,其他方法必须加static,才可以调用。

这里的methods();其实写全了,是Test.methods();

如果方法不加static,就得new一个test对象,来调用(因为对象能调用变量和方法)

5.5特殊的地方

1)main方法是特殊的,main方法为静态方法仅仅为程序执行入口,它不属于任何一个对象,可以定义在任意类中。main是虚拟机调用。

2)多态中也有特殊:

多态调用方法中,编译看左边,父类有,编译成功,父类没有,编译失败

运行静态方法,运行父类中的静态方法,

运行非静态方法,运行子类的重写方法(因为静态了,就属于类了)

成员变量,编译运行全是父类

例:

public class Father {
static int i=1;
public static void f(){
System.out.println("这是父类静态方法");
}
}
public class Son extends Father{
static int i=2;
public static void f(){
System.out.println("这是子类重写后的静态方法");
}
}
public class Test {
public static void main(String[] args) {
Father f=new Son();
System.out.println(f.i);
f.f();
}
}

5.6定义静态常量

静态常量一旦赋值,终身不变。可以类.变量名调用。

5.6.1定义格式:

  public static final 数据类型 变量名 = 值;

  (这里不一定非要Public,也可以私有,但是没意义,所以都是public)

5.6.2规则

static写final前面,

变量名全部大写,多个单词使用下划线连接。

例:public static final String SCHOOL_NAME = "北京大学";

Math.PI也是静态常量

5.6.3接口中的每个成员变量都默认使用 public static final 修饰。

所有接口中的成员变量已是静态常量,由于接口没有构造方法,所以必须显示赋值。可以直接用接口名访问。(因为用final定义的成员变量必须赋值)

构造方法,this,super,final,static的更多相关文章

  1. Java—构造方法及this/super/final/static关键字

    构造方法 构建创造时用的方法,即就是对象创建时要执行的方法. //构造方法的格式: 修饰符 构造方法名(参数列表) { } 构造方法的体现: 构造方法没有返回值类型.也不需要写返回值.因为它是为构建对 ...

  2. Java四个关键字 this super final static

    一.this ​ 关键字主要有三个应用: this调用本类中的属性,也就是类中的成员变量: this调用本类中的其他方法: this调用本类中的其他构造方法初始化对象,调用时要放在构造方法的首行. 引 ...

  3. 关键字this super final static

    this关键字 1.this代表通过当前类实例化成的对象. 2.通过this来获取当前类的属性和方法 3.通过this和区分成员变量和局部变量 4.通过this(参数),调用当前类的构造方法 注意:通 ...

  4. java中static,super,final关键字辨析

    1:static关键字 利:1)对对象的共享数据提供单独的空间存储. 2)修饰的方法可以直接被类名调用 弊:1)生命周期长. 2)访问出现限制(只能访问静态) 它可以有静态方法,静态类,静态变量 2: ...

  5. class 中的 构造方法、static代码块、私有/公有/静态/实例属性、继承 ( extends、constructor、super()、static、super.prop、#prop、get、set )

     part 1         /**          * << class 中的 static 代码块与 super.prop 的使用          *          * - ...

  6. java修饰符public final static abstract transient

    JAVA 修饰符public final static abstract transient  关键字: public final static abstract ...  1.public prot ...

  7. Java final static关键字

    Java中的final关键字 使用 final 关键字做标识有 “最终的” 含义. final 可以修饰 类.方法.属性.变量 final 修饰类: 则该类不允许被继承 final 修饰方法:则该方法 ...

  8. final&static

    final 1.final修饰类,那么该类不能有子类,那么也就没有子类重写父类的方法,也就没有多态 2.final修饰成员变量,那么成员变量要么显式赋值(用第一种),要么在构造方法中赋值 无论哪一种, ...

  9. 构造方法 this super

    1 构造方法 1.1 构造方法Constructor概述创建对象要明确属性值,此时需要用到构造方法,即对象创建时要执行的方法,用来给对象的属性进行初始化.在new对象时,知道其执行的构造方法是什么,就 ...

  10. JAVA 构造器, extends[继承], implements[实现], Interface[接口], reflect[反射], clone[克隆], final, static, abstrac

    记录一下: 构造器[构造函数]: 在java中如果用户编写类的时候没有提供构造函数,那么编译器会自动提供一个默认构造函数.它会把所有的实例字段设置为默认值:所有的数字变量初始化为0;所有的布尔变量设置 ...

随机推荐

  1. Godot-3D教程-01.介绍3D

    创建一个3D游戏将是个挑战,额外增加的Z坐标将使许多用于2D游戏的通用技术不再有用.为了帮助变换(transition),值得一提的是Godot将使用十分相似的API用于2D和3D. 目前许多节点是公 ...

  2. Poj_1068 Parencodings

    S     (((( )( )() ) ) ) P-sequence     4 5 6666,表示第i个右括号的左边有几个左括号. W-sequence    1 1 1456,表示第i个右括号和以 ...

  3. JMETER 定时器 之 常数吞吐量定时器

    定时器: 默认情况下,Jmeter线程在发送请求之间没有间歇.建议为线程组添加某种定时器,以便设定请求之间应该隔多长时间.如果测试人员不设定这种延迟,Jmeter可能会在短时间内产生大量访问请求,导致 ...

  4. 【241】◀▶IEW-Unit06

    Unit 6 Advertising 多幅柱子在一幅图中的写作技巧 1.Model1图片分析 The bar chart contains information about the amount o ...

  5. 【238】◀▶IEW-Unit03

    Unit 3 Media 柱状图 1.图片及model1分析 The graph below contains information about the average science test s ...

  6. Linux运行Tomcat下的war文件

    1.查看Tomcat进程: ps -ef |grep tomcat 2.关闭Tomcat进程: kill -9 pid 3.关闭Tomcat运行: bin目录下执行 ./shutdown.sh 4. ...

  7. Process 启动参数问题

    c#在有些情况下需要在启动另一个程序时传递参数,这里存在两个问题. 1.如果在参数里面含有空格,那么传递过去就会变成一个字符数组,这种情况是不满足情况的,解决方案是在传递参数时将空格用一些特殊字符替换 ...

  8. codeforces494C Helping People【treedp+概率dp】

    区间不交叉,可以看出区间构成了树形结构,建出树之后,设f[u][i]为u这个区间最大值最多加i的概率,转移是\( f[u][i]=p[u]*\prod f[v][mxu-mxv-1]+(1-p[u]) ...

  9. uoj#290. 【ZJOI2017】仙人掌(数数+仙人掌+树形dp)

    传送门 这图可以说是非常形象了2333 模拟赛的时候打了个表发现为一条链的时候答案是\(2^{n-2}\)竟然顺便过了第一个点 然后之后订正的时候强联通分量打错了调了一个上午 首先不难发现我们可以去掉 ...

  10. 程序员收藏必看系列:深度解析MySQL优化(二)

    程序员收藏必看系列:深度解析MySQL优化(一) 性能优化建议 下面会从3个不同方面给出一些优化建议.但请等等,还有一句忠告要先送给你:不要听信你看到的关于优化的“绝对真理”,包括本文所讨论的内容,而 ...