A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 庄星睿 中级黑马   /  2012-6-20 23:54  /  4177 人查看  /  20 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 庄星睿 于 2012-6-21 10:37 编辑

很多书上都写了this、super 写法,但基本上都是使用功能一样,写法不同,想了解一下在下面的程序里那种写法更好一些,更标准,效率更高
  1. class FuShuException extends Exception
  2. {
  3. private int value;
  4. public FuShuException(){}
  5. public FuShuException(String message)
  6. {
  7. super(message);
  8. }
  9. public FuShuException(String message,int value)
  10. {
  11. super(message);  //这里是用this(message);还是用super(message)那种更好
  12. this.value=value;
  13. }
  14. public int getValue()
  15. {
  16. return value;
  17. }

  18. }
复制代码
个人认为直接写super(message);好一点,直接调用父类的方法,减少了一次参数传递,还有下面的:
  1. class Person
  2. {
  3. private String name;
  4. private int age;
  5. public person(String name,int age)
  6. {
  7. this.name=name;  //这里写this.setName(name);
  8. this.age=age;    //这里写this.setAge(age);
  9. }

  10. public void setName(String name)
  11. {
  12. this.name=name;
  13. }
  14. public void setAge(int age)
  15. {
  16. this.age=age;
  17. }
  18. public String getName()
  19. {
  20. return this.name;
  21. }
  22. public int getAge()
  23. {
  24. return this.age;
  25. }
  26. public String getInfo()
  27. {
  28. return "学生信息:\n"+this.name+"\t"+this.age;
  29. //return "学生信息:\n"+this.getName()+"\t"+this.getAge(); //有些是这样写的,和上面的写法哪个好,更标准一些?
  30. }
  31. }
复制代码
很多书上都写的不同,有在构造函数中直接用this.name=name;但如果定义了setName()方法是不是优先用this.setName(name);这样做好像增加了一次参数传递了
但如果我setName()方法中设置了条件
pubilc void setAge(int age)
{
  if(!(age>0 && age<100))
      return;
  this.age=age;
   
}
构造器:
person(String name,int age)
{
   this.name=name;
   this.age=age;    //这样写,那么初始化new Person ("zhangsan",-300);初始化只有年龄符合int类型即可
   //this.setAge(age);  //这里new Person("zhangsan",300);这样写初始化会先调用判断
}
但又的书上写的是构造函数应该这样写
{
  this.name=name;
  this.age=age;// 尽量不用this.setAge(age);效率问题
}
构造函数里是不是得必须用this.setName(name)调用?还有上面的super 写法哪个更标准?

可能是我没有问清楚,我问的不是this 和super的使用问题,我问的是程序的标准写法的问题,在我的程序中,我标注了两种写法,但哪一种写法更优化,执行效率更高
就好比多次循环for(int i=0;i<1000000;++i)快于for(int i=0;i<1000000;i++)一样,具体开发中应该怎样写

20 个回复

倒序浏览
super 只适用子类调用父类。第一个例子用SUPER好点。
第二个例子,直接用this.name=name;和调用setName的区别在于前者你的setName里的条件设定就没用了
构造函数直接对NAME初始化,并传递给GETNAME,所以SETNAME里的条件设定被跳过了

回复 使用道具 举报
super是子类调用父类的同名方法或变量,同名方法即是子类重写了父类的方法,同名变量是子类中定义的成员变量与父类中的成员变量名相同,子类就隐藏了继承的成员变量,需要通过super方法才能调用。
this指针是表示调用该方法的当前对象,比如说有个函数为 int f(int a ,int b),那么 arr1.f(a,b)的话this指针就指向arr1所对应的参数,brr1.f(a,b)的话tihs指针就指向brr1所对应才参数,还有关于this指针的一点重要作用,也就是楼主你迷糊的地方,是参数名与变量名相同的情况下需要this指针加以区别。
class E
{
   int a;
   E(int a)
   {
     this.a=a;
  }
}
这个里面 参数列表中  a  与类的成员变量同名,需要this 指针加以区别,如果不同名你完全可以这样写
class E
{
   int a;
   E(int b)
   {
     a=b;
  }
}
不知楼主看懂没有,因为嘛,不同名的时候,你知道是要把b的值赋给a,同名的时候,计算机可就分不清哪个a是哪个a了,所以你要用this指针进行指向。
回复 使用道具 举报
本帖最后由 陆强强 于 2012-6-21 08:18 编辑

class E
{
   int a;
   E(int a)
   {
     this.a=a;
  }
}
用a=a;也是可以的。a=a不写THIS,new E()直接调用类E中的a,所以a=0.
写this的时候是把传入的A赋值给对象的A,a=2.
回复 使用道具 举报
李文龙 发表于 2012-6-21 02:06
super是子类调用父类的同名方法或变量,同名方法即是子类重写了父类的方法,同名变量是子类中定义的成员变 ...

可能是我没有问清楚,我问的不是this 和super的使用问题,我问的是程序的标准写法的问题,在我的程序中,我标注了两种写法,但哪一种写法更优化,执行效率更高
回复 使用道具 举报
先说第一个吧;
class FuShuException extends Exception

{
private int value;

public FuShuException(){}

public FuShuException(String message)

{

super(message);

}

public FuShuException(String message,int value)

{

super(message);  //这里是用this(message);还是用super(message)那种更好//建议先好好看看毕老师的this 和super关键字的用法;
                   //简单的说下;this代表本类引用;super代表引用父类的引用;这里的FushuException没有继承任何其它类;那么他的父类就只有Object,你确定Oject有这样
                 //的构造函数,如果有。你这样做的意义是什么;

this.value=value;

}

public int getValue()

{

return value;

}

}
class Person

{

private String name;

private int age;

public person(String name,int age)

{

this.name=name;  //这里写this.setName(name);//这里又是一个创建对象时;对对象成员变量及方法的初始化顺序的问题;创建对象过程中第一个执行的就是构造函数;  在不
                          //考虑父类super();的情况下;第一个执行的语句就是this.name=name; 如果你换成this.setName(name); 弱弱的问下;这个时候 的setName()方法都还没
                        //存在;你怎么给构造函数初始化;哥没有验证过、 因为这类的问题在论坛上太常见了;每天都有人问;都是同样的原理;为什么不去看别人提的问和解决方
                         //法呢;

this.age=age;    //这里写this.setAge(age);
}

public void setName(String name)

{

this.name=name;

}

public void setAge(int age)

{

this.age=age;

}

public String getName()

{

return this.name;

}

public int getAge()

{

return this.age;

}

public String getInfo()

{

return "学生信息:\n"+this.name+"\t"+this.age;
//return "学生信息:\n"+this.getName()+"\t"+this.getAge(); //有些是这样写的,和上面的写法哪个好,更标准一些?
}

}
回复 使用道具 举报
本帖最后由 陆强强 于 2012-6-21 08:42 编辑
庄星睿 发表于 2012-6-21 08:34
可能是我没有问清楚,我问的不是this 和super的使用问题,我问的是程序的标准写法的问题,在我的程序中, ...


第一个例子应该用SUPER
第二个例子看你的需求,如果变量没有条件限制就在构造函数里直接用this.name=name;这种格式
如果有需求还是调用SET的好
回复 使用道具 举报
邓杰 发表于 2012-6-21 08:39
先说第一个吧;
class FuShuException extends Exception

还是让事实说话吧:
  1. class Person
  2. {
  3. private String name;
  4. private int age;
  5. public Person(String name,int age)
  6. {
  7. //this.name=name;
  8. //this.age=age;
  9. this.setName(name);
  10. this.setAge(age);
  11. }

  12. public void setName(String name)
  13. {
  14. this.name=name;
  15. }
  16. public void setAge(int age)
  17. {
  18. if (!(age>0 && age <=100))
  19. return;
  20. this.age=age;
  21. }
  22. public String getName()
  23. {
  24. return this.name;
  25. }
  26. public int getAge()
  27. {
  28. return this.age;
  29. }
  30. public String getInfo()
  31. {
  32. //return "学生信息:\n"+this.name+"\t"+this.age;
  33. return "学生信息:\n"+this.getName()+"\t"+this.getAge();
  34. }
  35. }

  36. class Test
  37. {
  38. public static void main(String[] args)
  39. {
  40. Person p=new Person("张三",120);

  41. System.out.println(p.getInfo());
  42. }
  43. }
复制代码
程序问什么可以编译运行没问题呢?
这只能说明构造器是创建java对象,但不完全负责创建java对象,他是创建java对象的重要途径,通过new关键字调用构造器时,构造器也确实返回了该类的对象,但这个对象并不是完全由构造器负责创建的。实际上,当程序员调用构造器时,系统会先为该程序分配内存空间,并为这个对象执行默认初始化,这个对象以及产生了,这些操作在构造器执行之前就都完成了。只是所这个时候这个对象还不能被外部访问,只能在改构造器中通过this来引用。

评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 赞一个!

查看全部评分

回复 使用道具 举报

       super一个是指向当前类的对象,super是指向父类对象,其实他们的用法并不一样的.
       以super为例.
      它主要用在构造器中,当然也有在方法中使用,我不推荐这么用,既然是重载父类的方法,就没有必要调用父类的方法,当然也不能一概而论.super在子类访问父类的成员和行为,这就必须受类继承规则的约束,也就是说子类可见的资源才能被super 访问.而this就有点不一样,他代表当前对象,当然所有的资源都可以访问.
     在构造函数中,如果第一行没有写super(),编译器会自动插入.但是如果父类没有不带参数的构造函数,或这个函数被私有化了(用private修饰).此时你必须加入对父类的实例化构造.而this就没有这个要求,因为它本身就进行实例化的构造.
      而在方法中super和this使用的方法就差不多了.只不过super 要考虑是否能访问其父类的资源.
大多数情况下,我们都回采用默认的方式 ,即父类存在无参数的构造器,子类不用采用编译器默认的插入方式.但是我还是建议大家加上super()这句.这样程序的代码兼容性和结构性好.
回复 使用道具 举报
哥们你的第一个问题,
你的FushuException类没有继承其他的类,也就没必要用super了..
看你的代码
public FuShuException(String message)
{
super(message);
}
public FuShuException(String message,int value)
{
super(message);  //这里是用this(message);还是用super(message)那种更好
this.value=value;
}
下边的就是重载第一个的构造函数,在本类中自然而然用this了..


public person(String name,int age)
{
this.name=name;                     
this.age=age;   
}用这个构造函数的作用也就是为了方便给这个类中的属性赋值...
你说的那样就是错的,不能那样写..

实例化对象的初始化顺序:
1.对对象进行显示初始化
2.对对象进行构造代码块初始化、
3.对对象进行对应的构造函数初始化

因此不能写成:
this.setName(name);
this.setAge(age);
回复 使用道具 举报
庄星睿 发表于 2012-6-21 09:02
还是让事实说话吧:程序问什么可以编译运行没问题呢?
这只能说明构造器是创建java对象,但不完全负责创 ...

向你学习了;以前还真不是知道;
谢谢;
回复 使用道具 举报
常佳杰 发表于 2012-6-21 09:38
哥们你的第一个问题,
你的FushuException类没有继承其他的类,也就没必要用super了..
看你的代码
  1. class Person
  2. {
  3. private String name;
  4. private int age;
  5. public Person(String name,int age)
  6. {
  7. //this.name=name;
  8. //this.age=age;
  9. this.setName(name);
  10. this.setAge(age);
  11. }

  12. public void setName(String name)
  13. {
  14. this.name=name;
  15. }
  16. public void setAge(int age)
  17. {
  18. if (!(age>0 && age <=100))
  19. return;
  20. this.age=age;
  21. }
  22. public String getName()
  23. {
  24. return this.name;
  25. }
  26. public int getAge()
  27. {
  28. return this.age;
  29. }
  30. public String getInfo()
  31. {
  32. //return "学生信息:\n"+this.name+"\t"+this.age;
  33. return "学生信息:\n"+this.getName()+"\t"+this.getAge();
  34. }
  35. }

  36. class Test
  37. {
  38. public static void main(String[] args)
  39. {
  40. Person p=new Person("张三",120);

  41. System.out.println(p.getInfo());
  42. }
  43. }

复制代码
程序问什么可以编译运行没问题呢?
这只能说明构造器是创建java对象,但不完全负责创建java对象,他是创建java对象的重要途径,通过new关键字调用构造器时,构造器也确实返回了该类的对象,但这个对象并不是完全由构造器负责创建的。实际上,当程序员调用构造器时,系统会先为该程序分配内存空间,并为这个对象执行默认初始化,这个对象以及产生了,这些操作在构造器执行之前就都完成了。只是所这个时候这个对象还不能被外部访问,只能在改构造器中通过this来引用。

还有你没细看我的程序,class FuShuException extends Exception ,他是继承了Exception 类的
回复 使用道具 举报
本帖最后由 陆强强 于 2012-6-21 10:03 编辑

先不说代码规范不规范,如果我Person p=new Person("张三",-120);
你用public Person(String name,int age)
{
this.name=name;
this.age=age;
}
去试试,他打印的是
张三   -120
你觉得这代码还有意义么
public Person(String name,int age)
{
this.setName(name);
this.setAge(age);
}
的结果是
张三    0
那是因为它SETname 里返回的是空。也可以改成抛异常然后加上输入不合法等信息
回复 使用道具 举报
陆强强 发表于 2012-6-21 09:58
先不说代码规范不规范,如果我Person p=new Person("张三",-120);
你用public Person(String name,int age) ...

标准开发的时候怎样写?
还有后面的
return "学生信息:\n"+this.name+"\t"+this.age;
return "学生信息:\n"+this.getName()+"\t"+this.getAge();
标准开发的时候应该怎写,选哪一个,为什么?
回复 使用道具 举报
本帖最后由 陆强强 于 2012-6-21 10:34 编辑

class Person
{
private String name;
private int age;
public Person(String name,int age)
{
this.setName(name);

this.setAge(age);
}
public void setName(String name)

{

this.name=name;

}

public void setAge(int age)

{

if (age<=0||age>=100)
                throw new RuntimeException("年龄输入错误,请输入0到100数字");
this.age=age;

}



public String getName()
{
return this.name;
}
public int getAge()
{
return this.age;
}
public String getInfo()
{
return "学生信息:\n"+this.name+"\t"+this.age;
//return "学生信息:\n"+this.getName()+"\t"+this.getAge();
}
}

class Test
{
public static void main(String[] args)
{
Person p=new Person("张三",120);

System.out.println(p.getInfo());
}
}
这样最大的好处是符合实际,一个是不能输入0-100以外的年龄,另一个是可以对AGE用Set方法修改
第二个问题;return "学生信息:\n"+this.name+"\t"+this.age;
这个好一点区别不大,this这里可以省略不写
回复 使用道具 举报
陆强强 发表于 2012-6-21 10:26
class Person
{
private String name;

呵呵,这个问题困扰了很长时间了,查了很多书,每一本书写的都不一样,有的书上说构造器应该这样写
{
   this.name=name;
   this.age=age;
}
那个return 的个人感觉还是this.name+this.age,效率好一点,
就好像老外写Iterator用for(Iteratr it=XXX.iterator();it.hasNext();)不用while
不管怎样我还是以老外的为准吧,毕竟老外编的书是没错的
回复 使用道具 举报
庄星睿 发表于 2012-6-21 10:47
呵呵,这个问题困扰了很长时间了,查了很多书,每一本书写的都不一样,有的书上说构造器应该这样写
{
    ...

{
   this.name=name;
   this.age=age;
}
毕老师也这么写的,不过他也说明了那是为了方便演示,因为这样可以直接初始化不用SET方法了
SET方法不写也没关系
回复 使用道具 举报
好吧,我来说说我的意见吧。
第一个问题:子类继承父类,连着父类的属性也继承了,用super说明你是给继承过来的父类属性赋值,用this说明你给本类建立的属性赋值,如果用this,就得在本子类中加入一个private String message,你这个程序没加,所以你觉得你可以用this么?再想一下,如果你要自己加一个和已经继承有的属性一样的东西,等于覆写吧,那还要继承干嘛,浪费时间和空间,所以第一个用super。
第二个问题:为什么加getName,getAge这两个函数?就是因为类中的name和age属性已经封装了,是私有的,所以才要放这两个函数出去给其他对象访问,注意是其他对象,而你在构造器和类中赋值函数的时候,完全是在自己类中,完全可以直接用this.name引用,干嘛要用给外人的方法给自己赋值,就像你在家里面跟老爸打招呼,不直接说:唉,老爸回来了?而是说:唉:某某某(老爸的名字),你回来了!!这不是见外嘛?还多此一举~~~搞不好老爸还赏个耳刮子过来呢!!你说哪个好吧!!

评分

参与人数 1技术分 +1 收起 理由
职业规划-刘倩老师 + 1 赞一个!

查看全部评分

回复 使用道具 举报
黄奕豪 发表于 2012-6-21 15:29
好吧,我来说说我的意见吧。
第一个问题:子类继承父类,连着父类的属性也继承了,用super说明你是给继承过 ...

这样的回答即精辟简洁,又生动有趣,希望能多看到这样的回帖!
回复 使用道具 举报
李元峰 发表于 2012-6-21 15:38
这样的回答即精辟简洁,又生动有趣,希望能多看到这样的回帖!

:)你们也可以啊!!看到原创的我一般都给分!!
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马