package demo; public class demo { double length=10; double height=5; public demo(doublel,double h) { length=l; height=h; } double area() { returnlength*height/2.0; } public static voidmain(String args[]) { doubles; s=(new demo()).area(); System.out.println("area="+s); } } //注意这个例子中new demo()中不给参数是错误的, 好像给了构造函数就不会再给默认构造函数了
这个例子是错的, 改成new demo(100,50)就对了,或者去掉构造函数也是对的。
c++中这样是对的,在java中不给出构造函数的话,会的调用默认的构造函数,一旦你给出了自己的构造函数,默认的构造函数将无法被调用。
所以,如果Java中父类没有默认构造函数,子类一定要有一个构造函数显式调用父类的非默认构造函数
默认构造函数也可以显式写出来,这样子类就不用显示调用了,比如:
public class MyTest {
MyTest(int a)
{
}
}
class MyNewTest extends MyTest{
}///这样是错误的,没有显式调用父类的非默认构造函数
public class MyTest {
public MyTest(int a)
{
}
public MyTest()
{
}
}
class MyNewTest extends MyTest{
}//这样是正确的,构造子类时调用父类和子类的默认构造函数
public class MyTest {
public MyTest(int a)
{
}
}
class MyNewTest extends MyTest{
public MyNewTest(int a) {
super(a);
}
}//正确
2.构造函数没有返回值,不要返回void,如果返回了void,不认为是构造函数
public class MyTest {
public void MyTest(int a)
{
}
}
class MyNewTest extends MyTest{
}//这样也正确
MyTest test = new MyTest(1);//错误,不认为public void MyTest(int a)是构造函数
MyTest test = new MyTest();//正确
3.同一个包里的类,可以直接使用,不要import
4.java的回调就是类似于观察者模式:
程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序。程序员B要让a调用自己的程序b中的一个方法,于是,他通过a中的接口回 调自己b中的方法。目的达到。在C/C++中,要用回调函数,被掉函数需要告诉调用者自己的指针地址,但在JAVA中没有指针,怎么办?我们可以通过接口 (interface)来实现定义回调函数。
假设我是程序员A,以下是我的程序a:
- public class Caller
- {
- public MyCallInterface mc;
- public void setCallfuc(MyCallInterface mc)
- {
- this.mc= mc;
- }
- public void call(){
- this.mc.method();
- }
- }
我还需要定义一个接口,以便程序员B根据我的定义编写程序实现接口。
- public interface MyCallInterface
- {
- public void method();
- }
于是,程序员B只需要实现这个接口就能达到回调的目的了:
- public class B implements MyCallInterface
- {
- public void method()
- {
- System.out.println("回调");
- }
- public static void main(String args[])
- {
- Caller call = new Caller();
- call.setCallfuc(new B());
- call.call();
- }
- }
Java中字符串连接有好多种写法,比如要连接6个字符串,以下5种写法都是可以的,究竟哪种写法最简捷,哪种最高效呢。
public static String concat1(String s1, String s2, String s3, String s4, String s5, String s6) {
String result = "";
result += s1;
result += s2;
result += s3;
result += s4;
result += s5;
result += s6;
return result;
}
public static String concat2(String s1, String s2, String s3, String s4, String s5, String s6) {
StringBuffer result = new StringBuffer();
result.append(s1);
result.append(s2);
result.append(s3);
result.append(s4);
result.append(s5);
result.append(s6);
return result.toString();
}
public static String concat3(String s1, String s2, String s3, String s4, String s5, String s6) {
return new StringBuffer(s1.length() + s2.length() + s3.length() + s4.length() + s5.length() + s6.length())
.append(s1).append(s2).append(s3).append(s4).append(s5).append(s6).toString();
}
public static String concat4(String s1, String s2, String s3, String s4, String s5, String s6) {
return s1 + s2 + s3 + s4 + s5 + s6;
}
public static String concat5(String s1, String s2, String s3, String s4, String s5, String s6) {
return new StringBuilder(s1.length() + s2.length() + s3.length() + s4.length() + s5.length() + s6.length())
.append(s1).append(s2).append(s3).append(s4).append(s5).append(s6).toString();
}
第一种写法是最土的写法,也最累赘,事实上看到这样的代码我都会有点头疼。看过《Effective Java》的朋友都知道用StringBuffer吧,用第二种写法的人应该也不少。第4种写法当然最简捷,最优美的了,就是不知道性能怎么样。Java 5里加了个StringBuilder类,与StringBuffer功能一样,就是没有同步,所有用StringBuilder代替 StringBuffer肯定对性能有好处,这样就产生的第5种写法。
还是做个测试有说服力。我的机器上同时装了JDK 5和JDK 6,两个都测了一下。执行每个函数10000000次(输入的每个参数都是"a"),各种写法用时如下,单位毫秒:
JDK 5:
concat1: 13776
concat2: 5081
concat3: 4944
concat4: 4202
concat5: 4047
JDK 6:
concat1: 11801
concat2: 3930
concat3: 3976
concat4: 3353
concat5: 3440
可以看出第1种写法果然最慢,第二种写法由于用了StringBuffer,快了很多。奇怪的是第4种写法竟然也很快,比用StringBuffer还快,怎么回事?其实如果你调试过字符串连接的执行过程就会知道当用第4种写法时Java会自动使用StringBuilder.append()函数来进行连接。所以最简捷的第4种写法已经够快了。在JDK 5里,第5种写法最快,因为在创建StringBuilder的时候预先计算了总长度,消除了内存重分配。不过没有必要这么写,JDK 6里已经为第4种写法做了更好的优化,第5种写法反而慢了。
由此可见,采用最简单的第4种写法对于Java的实现来说优化的可能性越大。就像SQL一样,由于采用了陈述式的写法,优化器才有了优化的余地。想起了两句话:
1. 简单即美,谁都希望看到简洁明快的代码,不希望看到冗长乏味的代码
2. 性能优化是万恶之源
6.外部类对于内部类的所有元素也都有访问权,包括内部类的私有成员和方法