Think in java 中的记录
-
return的作用
- 一种是返回参数所用的关键字,假如一个有返回值的方法执行完了之后需要返回一个参数
public string functionTest(){ String a = "abc"; return a; } string result = functionTest();//返回结果为abc的result
- 代码执行到此处终止。比如当代码执行到某个地方会出现几种结果,然后其中一种结果就不能执行后续代码,这时候在那里加上一个return就可以终止后面的代码执行。
-
数组
- String[] a 对象数组象中的每个元素都是对的管理者而非对象本身
-
super:
- super.xxx;(xxx为变量名或对象名)
这种方法意义为,获取父类中的名字为xxx的变量或方法引用。
使用这种方法可以直接访问父类中的变量或对象,进行修改赋值等操作 - super.xxx();(xxx为方法名)
这种方法意义为,直接访问并调用父类中的方法。 - super();
这种方法意义为,调用父类的初始化方法,其实就是调用父类中的public xxx()方法;
- super.xxx;(xxx为变量名或对象名)
-
子类父类关系:
子类不能调用父类的private 变量 protected可以 出现同名成员变量是,就近原则
子类也是父类的一种扩展 父类可以直接调用子类
子类的对象可以赋给父类的对象
父类对象转化为子类对象 :- Son son=(Son)Parent parent; //只有当parent这个变量实际管理的是son才可以 ,这称为造型 Parent parent=(Parent)Son son;//向上造型 拿一个子类对象给父类用,默认安全 public class test1{ private String s="a"; test1(){ System.out.println("test1()"); } test1(int i){ System.out.println(i); System.out.println(s); } static void test2(test1 i){ System.out.println(" 向上转型"); } } class frog extends test1{ } public class Extend_exam { public static void main(String []args) { frog fr=new frog(); test1.test2(fr); }
函数调用的绑定:
当通过对象变量调用函数的时候,调用哪个函数这件事情叫作绑定。
静态绑定:根据变量的声明类型来决定
动态绑定:根据变量的动态类型来决定
在成员函数中调用其他成员函数也是通过this这个对象变量来调用的
java中默认对象的绑定是动态绑定
@Override
//子类和父类中存在名称和参数完全相同的函数,这一对函数构成覆盖,子类覆盖父类 ,需要注意的是只有父类中非private的方法才可以被覆盖,在导出类中,对于基类中的private方法,最好采用不同的名字。
public class PrivateOverride {
private void f() {
System.out.println("private f()");
}
public static void main(String []args) {
PrivateOverride a=new Derived();
a.f();
Derived b=new Derived();
b.f();
b.f1();
//a.f1(); 这样的操作也是不被允许的
}
}
class Derived extends PrivateOverride{
public void f() {
System.out.println("public f()");
}
public void f1() {
System.out.println("这是导出类中的f1()方法");
}
}
//output:
private f()
public f()
这是导出类中的f1()方法
String 字符串分割:split() 方法用于把一个字符串分割成字符串数组。
-
抽象:
抽象函数:{表达概念而无法实现具体代码的函数
抽象类:表达概念而无法构造出实体的函数
-
区别
有抽象函数的类一定是抽象类
抽象类不能制造对象但是可以定义变量,任何继承了抽象类的非抽象类的的对象可以赋给这个变量
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。
构造方法,类方法(用static修饰的方法)不能声明为抽象方法。
抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。
在其他方面,抽象类和普通的类并没有区别。
-
interface接口:
- 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
- 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口
例子: Door的open() 、close()和alarm()根本就属于两个不同范畴内的行为,open()和close()属于门本身固有的行为特性,而alarm()属于延伸的附加行为。因此最好的解决办法是单独将报警设计为一个接口,包含alarm()行为,Door设计为单独的一个抽象类,包含open和close两种行为。再设计一个报警门继承Door类和实现Alarm接口。
interface Alram { void alarm(); } abstract class Door { void open(); void close(); } class AlarmDoor extends Door implements Alarm { void oepn() { //.... } void close() { //.... } void alarm() { //.... } }
-
在文件流上建立文本处理:
PrintWriter pw=new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream("abc.txt"))));
-
显式的静态初始化
public class Spoon{ static int i; static{ i=47; } }
-
int与integer的对比:
Integer是int的包装类;int是基本数据类型
integer变量必须实例化后才能使用;int变量不需要
intege实际是对象的引用,指向此new的integer对象,int是直接存储数据值
integet的默认值是null,int的默认值是0;{ Integer i= new Integer(100); Integet j=new Integer(100); System.out.println(i==j);//false } { Integet i=new Integer(100); int j=100; System.out.println(i==j);//true } { Integer i=new Integet(100); Ingeter j=100; System.out.println(i==j);//false 非new生成的Integer变量指向的是java常量池中的对象,new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同 }
-
组合,继承,代理:
组合:在新类中new 另外一个类的对象,以添加该对象的特性。
继承:从基类继承得到子类,获得基类的特性。当继承发生时,编译器会从先对基类进行初始化。
代理:在代理类中创建某功能的类,调用类的一些方法以获得该类的部分特性。
-
使用场合:
组合:各部件之间没什么关系,只需要组合即可。like组装电脑,需要new CPU(),new RAM(),new Disk()……
继承:子类需要具有父类的功能。基类无法调用子类方法。
代理:飞机控制类,我不想暴露太多飞机控制的功能,只需部分前进左右转的控制(而不需要暴露发射导弹功能)。通过在代理类中new一个飞机控制对象,然后在方法中添加飞机控制类的各个需要暴露的功能。
-
public private protected default的区别:
- public:可以被所有其他类所访问
- private:只能被自己访问和修改
- protected:自身、子类及同一个包中类可以访问
- default:同一包中的类可以访问,声明时没有加修饰符,认为是friendly。
-
final:
修饰基础数据成员的final
这是final的主要用途,其含义相当于C或者C++的const,即该成员被修饰为常量,意味着不可修改。如java.lang.Math类中的PI和E是final成员,其值为3.141592653589793和2.718281828459045。修饰类或对象的引用的final
在Java中,我们无法让对象被修饰为final,而只能修饰对象的引用,这意味着即使你写public final A a = new A(); 事实上a指向的对象的数据依然可以被修改,不能修改的是a本身的引用值,即你不能再对a进行重赋值。同样的情况出现在数组中,比如public final int[] a = {1, 2, 3, 4, 5},事实上a中的数值是可修改的,即可以写a[0] = 3。据目前了解,java中数组内的数据是无法修饰为不可修改的,而C/C++可以。-
修饰方法的final
修饰方法的final和C/C++中修饰成员对象的const大不相同。首先,修饰方法的final含义不是“不可修改”,而是指该方法不可被继承成员重新定义。(注意,这里所说的不能被重新定义,并不是指子类一定不能定义同名方法,如果父类的方法是私有类型,子类是允许定义该方法的,这里指的不能重新定义是指不能通过改写方法来使得方法重写的多态性得以实现,如不希望A a = new B(); a.f();这样的重写方法情况出现)
示例:public class A { // final方法f public final void f() { System.out.println("类A中的final方法f被调用了"); } } public class B extends A { // 编译错误!父类的f方法是final类型,不可重写! //! public void f() { //! System.out.println("类B中的方法f被调用了"); //! } }
+ 此外,当一个方法被修饰为final方法时,意味着编译器可能将该方法用内联(inline)方式载入,所谓内联方式,是指编译器不用像平常调用函数那样的方式来调用方法,而是直接将方法内的代码通过一定的修改后copy到原代码中。这样可以让代码执行的更快(因为省略了调用函数的开销),比如在int[] arr = new int[3]调用arr.length()等。
另一方面,私有方法也被编译器隐式修饰为final,这意味着private final void f()和private void f()并无区别。
-
修饰类的final:
当一个类被修饰为final时,它的含义很明确,就是不允许该类被继承,也就是说,该类“绝后”了,任何继承它的操作都会以编译错误告终。这也凸显出Java用final而不用const作为标识符的理由。
示例:public final class A { } // 编译错误!A是final类型,不可被继承! //!public class B extends A{ //!}
- final和static final的区别:
{
class SelfCounter{
private static int counter;
private int id = counter ++; //下一次实例化该类时才会id的值才等于这一次的counter+1;
public String toString(){
return "SelfCounter :" + id;
}}
class WithFinalFields{
static final SelfCounter wffs = new SelfCounter();
final SelfCounter wff = new SelfCounter();
public String toString(){
return "wff = " + wff + "\n wffs = " + wffs;
}
}
public class E18_StaticFinal {
public static void main(String[] args) {
System.out.println("First Object :");
System.out.println(new WithFinalFields());
System.out.println("Second Object: ");
System.out.println(new WithFinalFields());
}},
运行结果是
First Object :wff = SelfCounter :1 wffs = SelfCounter :0
Second Object: wff = SelfCounter :2 wffs = SelfCounter :0
结论:
static的常量在类加载的时候被初始化,而实例常量在实例化的时候被初始化。其实上面的过程很简单。第一次实例化WithFinalFields的时候,虚拟机发现该类没有被加载,于是先加载类,加载类的同时需要初始化类的所有static无论是变量、常量还是块,于是wffs需要实例化一个SelfCounter对象,这个时候虚拟机发现SelfCounter类也没有被加载,于是加载SelfCounter类,同时初始化static变量counter为0,加载SelfCounter类完毕,开始实例化SelfCounter对象,初始化id为0(此时counter为0),同时counter变为1,这时SelfCounter对象的实例化完毕,并被赋值给WithFinalFields类的wffs常量,加载WithFinalFields类的过程完毕,开始正式实例化WithFinalFields对象,初始化wff常量,又需要实例化一个SelfCounter对象,这时虚拟机发现SelfCounter类已经被加载,于直接开始实例化SelfCounter对象,初始化id为1(此时counter为1),同时counter变为2,实例化WithFinalFields对象完毕,此时wffs的id为0,wff的id为1。第二次实例化WithFinalFields的时候,虚拟机发现该类已经被加载,直接实例化,不会初始化static无论是变量、常量还是块,于是直接初始化wff常量,需要实例化SelfCounter对象,该类也已经被加载,于是也直接实例化,初始化id为2(此时counter为2),同时counter变为3,实例化SelfCounter对象完毕,同时实例化WithFinalFields对象完毕,此时wffs的id仍然为0,wff的id为2。重点是静态的东西只会被初始化一次,发生在类加载的时候。