●Path:jdk1.7\bin,是Javac.exe和Java.exe的所在目录,path中越靠前越先找。Classpath,默认是在当前目录找.class文件,如果字节码不在当前目录就设个classpath。
Javac –d .\com Test.java,则Test.class存在当前目录下的com子目录中。
Java –cp .\com Test,运行com里的字节码。-cp和classpath冲突时考虑-cp。
●书是类,Java书是对象,Book javaBook=new Book(); new在堆空间生成对象,javaBook是对对象的Book类引用。即:引用是绳子,对象是气球,一个气球可以有多个绳子引用,单一时间一个绳子只能引用一个气球,没有绳子时,气球就飞了。
●如果一个Java源文件定义了多个类,其中只能有一个是public的,也可以都不是public,包含main方法的类名与文件名相同。
●Java虚拟机可以理解成一个以字节码(.class)为机器指令的CPU。
●main函数是门,是入口,当然你也可以跳窗户,但房间是封闭的,你就只能走门了。
●千万不要用拼音命名变量,那真的是太不专业了,一定要用英文,这样每个人都能知道是什么意思。
●参数传递只有一种方法,就是传值:传变量值,和传地址值,没有传引用机制。
●局部变量定义时必须赋初值,因为成员变量有构造函数赋初值,参数有传递值。
●编译器是靠参数区分重载(overlode),所以void m(int a)| int m(int a)编译不能通过。但如果第二个的参数改为double类型就能通过。参数顺序变化也构成重载,参数的名称无所谓。
重载的目的通常是对不同的数据类型完成相同的操作。
●关于重载方法的选择顺序:无论是基本类型还是引用类型,系统会优先调用形参与实参完全相同的方法,如果这样的方法不存在,就选择向上提上一级的方法(char提升一级为int,子类提升一级为父类),然后是自动封箱与拆箱,最后考虑可变的参数类型。如果一步中可选的方法有两个(比如双参,方法1一参相同一参升一级,方法二一参升一级一参相同),系统就会报错。
关于多态类的引用,Father fa = new Son();将调用形参为父类的方法。Int m(Father fa);&Int m(Son son).即方法重载发生在编译器,并不知道具体引用的对象。另一个编译期绑定(静态绑定)的例子是静态方法调用,多态将执行父类的方法,根据引用的类型决定执行哪个方法。而实例方法的调用是动态绑定的,根据真正对象的类型决定执行哪个方法。
●方法重写(override)要求返回类型一样、名称一样、参数一样,即标题头一行复制粘贴。重写(覆盖)就是全部擦掉再写,如果想"继承"后加内容就加个super.show();无论是重载还是重写或者定义新的方法,都可以使用super.show();因为show()是普通方法。重写要求子类和父类的方法都不是静态方法,否则编译报错,两者都是静态方法则是隐藏。
重写发生在父类和子类之间,重载发生在同一类之中。重写的访问修饰符一定要大于被重写方法的访问(public>default),重写方法的抛弃异常必须比被重写方法的抛弃异常范围小。在JDK1.5以后,允许子类方法的返回类型是父类的子集,包括子类是父类的子集。
●构造方法只能用public、private系列四个修饰,不能用别的任何修饰(static,final、void)。如果构造方法里加一句打印语句,则Book book1=new Book();时调用构造方法自动打印。构造方法也能重载,只需看参数。This(3)调用当前类里面接受一个整形参数的构造方法。调用其他构造方法的this必须是构造方法的第一条语句。
●This是一个引用,引用的是该方法所在的对象。不能再静态方法里使用this,因为用类的名字访问对象时,如果没有生成对象,这时this不知道是哪个对象。
●继承时,默认调用父类不带参数的构造方法,生成父类的对象,然后调用子类的构造方法,生成子类的对象,即没有父类就没有子类。构造方法不能继承。如果父类只有自定义的构造方法,就必须在子类的构造方法里加一句super(2)(父类的构造方法参数是整型),且必须是构造方法的第一句。
●继承:父类有的,子类也有。父类没有的,子类可以增加。父类有的,子类可以改变。如父类的成员变量没有被子类隐藏,则两者共用同一个成员变量。
●多态:先找父类是否拥有此方法,若有按子类的方法执行,指向谁执行谁。父类没有就不能执行,编译错误,除非强制转换成子类引用。父类没有的成员变量也不能访问。父类型的引用可以指向子类的对象,指向后可以随时指回父类对象。父类型的引用(指向子类对象时)转换成子类型的引用(向下)需强制转换。父类对象的引用(无多态时)强制转换成子类型的引用是不行的,指向谁才能类型转换谁,不能给动物强制转换成猫,也不能给猫强制转换成狗。多态的第二层含义是抽象类或接口指向实现他们的实例。
●Cat cat=new Cat();
Animal animal=cat;相当于Animal animal=(Animal) cat;省略不写即普通的多态是向上类型转换,不需强制,(new出来的是cat类的对象,转换就父类的引用即是向上)。即猫肯定是动物,但动物不等价于猫。
Cat cat2=(Cat) animal;向下,必须有括号强制。
●继承和多态的区别是:继承子类独有的方法和成员变量可以执行,多态子类独有的方法不能执行,子类独有的成员变量也不能访问。两种隐藏(见下)多态都指向的是父类。相同是:都包含继承,当有三代类时,方法和属性会一代代的继承下去,爷类也可以指向孙类,Grandpa gp=new Son();。对于子类重写的方法,继承和多态都调用子类的方法。
-
public class TestCar {
-
-
public static void main(String[] args) {
-
-
Car car = new Car(40);
-
Bus bus = new Bus(20,10);
-
-
System.out.println("Car速度: " + car.v);
-
System.out.println("Bus速度: " + bus.v);
-
//将子类bus的引用赋给父类的对象
-
//此时子类中那些不是从父类继承而来的成员将不再可见。不能打印car.p。
-
car = bus ;
-
System.out.println("Car1速度: " + car.v);
-
//我们可以通过强制类型转换将这个父类再转换成子类类
-
//此时那些不见了的成员又变得可见了。
-
Bus bus2 = (Bus)car;
-
System.out.println("Car1速度: " + bus2.p);
-
//由此可见,将子类引用赋给父类对象时,java虚拟主机并没有将那些非继承成员丢弃
-
}
-
}
-
-
-
class Car{
-
int v;
-
public Car(int v){
-
this.v = v;
-
}
-
}
-
-
-
class Bus extends Car{
-
//int v=10;
-
int p;
-
public Bus(int v , int p){
-
super(v);
-
this.p = p;
-
}
-
}
子类没有int v=10时,父类和子类共用一个成员v,子类的构造方法是通过super给父类的成员赋值20,输出:
Car速度: 40
Bus速度: 20
Car1速度: 20
Car1速度: 10
子类有int v=10时,子类的v隐藏了父类的v,子类的为10,父类的为20。输出:
Car速度: 40
Bus速度: 10
Car1速度: 20
Car1速度: 10
●多态的作用是:
Car car = new BMW();
car.run();
car= new QQ();//此句千万不能写成Car car=new QQ();犯过一回错误,这样就重复生成相同名字的变量了。
car.run();
父类可以一会指向这个子类(QQ)一会指向另一个子类(BMW),但子类的引用之间不能强制转换(QQ和BMW,就像猫和狗)。如果没有多态,就得生成一个BMW的引用,生成一个QQ的引用,且分别调用run方法。当然,用多态子类也得改写run方法。
●隐藏(Hide)和方法重写(覆盖)的区别:重写是引用指向谁就调用谁的方法,多态会调用子类。隐藏是什么类型的引用就调用谁的方法,多态会调用父类,包括继承中变量隐藏和Static方法隐藏。将父类的int x=0隐藏为double x=1,或者父类定义int x=10,子类定义int x=100,都是隐藏。static int x也可以隐藏。必须新定义一个同名成员变量才能隐藏,没隐藏时父类、子类共用一个成员。变量隐藏和局部变量{ int I;}隐藏外部变量相似。
-
class Book extends Test{
-
int a=10;
-
void f()
-
{
-
System.out.println(a);
-
}
-
}
-
-
-
public class Test {
-
int a=0;
-
void f()
-
{
-
System.out.println(a);
-
}
-
public static void main(String[] args)
-
{
-
Book book=new Book();//子类引用
-
book.f();
-
System.out.println(book.a);
-
Test t=new Test();//父类引用
-
t.f();
-
System.out.println(t.a);
-
t=book;
-
t.f();
-
System.out.println(t.a);
-
}
-
}
输出结果为:
10
10
0
0
10
0
当
-
void f()
-
{
-
int a=10; //a只生存在方法f中
-
System.out.println(a);
-
}
-
}
输出结果为:
10
0
0
0
10
0
只第二个Book.a发生变化。
因为方法结束后为方法中局部变量分配的内存空间全部消失。
即谁的方法就调用谁的成员变量,继承了父类的方法就用父类变量,重写了父类的方法就用子类的变量。多态调用子类重写的方法时,引用子类的变量,直接调用子类同名变量(变量的隐藏)则调用父类的变量。可以想象成狗跑的方法跟腿有关系,腿长的狗跑的快,谁跑用谁的腿。单独拿出一个腿拿出是父类的腿。
另一种是Static方法隐藏。
-
public class StaticTest {
-
-
public static void main(String[] args) {
-
B b=new B();
-
System.out.println(b.x);//B.x
-
b.a(2,3); //等价于B.a(2,3)
-
b.a(2); //等价B.a(2)
-
}
-
-
}
-
class A {
-
static int x=0;
-
static void a(int i)
-
{
-
System.out.println(x);
-
}
-
}
-
-
class B extends A {
-
static double x=1;
-
static void a(int i,int j)
-
{
-
System.out.println(x);
-
}
-
}
运行结果为1.0,1.0,0.这里面子类B隐藏了父类A的Static变量x,又重载了父类的static方法。谁的方法就调用谁的变量,继承自父类的方法也是父类的。
如果将B b=new B();改为多态A b=new B();则不能调用b.a(2,3);因为重载只属于子类,和Static和隐藏都没关系(把两个Static去掉也不能调)。结果为0,0。
●晚绑定就是运行时绑定,可以通过args传参数来确定。多态是一种运行期的行为,而不是编译期的行为,编译期只能读出引用是什么类型,不能看出是指向什么。
●内存:引用是一小块内存指向一大块内存,对象保存在堆空间里,运行时执行,因为编译不知道它占多大空间。不同的对象保存着独自的成员变量(除了static变量),还保存着所有父类的被隐藏的成员变量(所以多态能指向父类的变量)。而方法只有一份,执行的时候才占用内存。成员变量的生存期是整个类,方法内局部变量的生存期是方法内。
●对于所有引用变量,并不需要所谓的初始化操作,需要进行初始化操作的是该引用变量所指的对象。语句Parent P;是可以的,没有初始化,它指向的Null。比如,数组变量不需要初始化操作,而数组对象本身需要进行初始化。所有局部变量都是放在栈内存里保存的,不管其实基本类型还是引用类型的变量,都是存储在各自的方法栈区中;但引用类型变量所引用的对象(包括数组、普通的Java对象)则总是存储在堆空间中。
●抽象类:abstract修饰的类。抽象方法:abstract修饰的方法,不能有花括号即不能实现,且必须定义在抽象类中。如果一个类包含抽象方法,则该类一定是抽象类。但一个抽象类中也可以全部都是具体方法。
子类要继承抽象类,必须实现(覆盖)抽象类中全部的抽象方法。抽象类继承抽象类,不必要实现抽象方法(也可以实现),但仍不能实例化。抽象类能继承抽象类,抽象方法不能用static修饰。
抽象类可以通过子类多态来实现。Bookabst book=new Book(320,"java");来调用子类的构造方法。子类对抽象类方法的实现相当于重写,所以可以调用book.show();(抽象类中有抽象方法show)
●接口:Interface。和类同等级,接口中的所有方法都默认是抽象方法。接口可以extends多个接口类和抽象类implements接口。如果接口定义为Public的,则文件名得改为接口名.java。接口不能有构造方法,且接口中方法默认是public的,重写的方法也必须是public。一个类必须实现接口的所有方法,否则是抽象类。一个类可以实现多个接口,接口间就用逗号分隔。接口也能实现抽象类似的多态。接口的属性默认是public static final的,定义时必须赋值。Java中常量的默认定义也是public static final的。
Class MyClass extends MyParent implements MyInterface,Myinterface2
既继承又实现两个接口。
Interface里包含了Object类所有方法对应的抽象方法,即一个类实现了一个空接口就能直接调用object含有的所有方法,因为这个类也来自于object类。
●static:可以修饰类,也可以修饰成员和方法。Static变量,类变量,所有对象共用。public static int binarySearch是静态方法,可在main里直接调用。Main函数也是静态方法。普通的静态方法都是实现一个数学运算,如斐波那契,除了用到传入参数以外不和外面的数据发生关系,也就不会引用到外面的非静态变量,内部的就无所谓了。
●静态(类)方法只能处理静态变量,调用静态方法。静态变量和静态方法是属于类的,一个对象对他们进行了修改,其他对象访问的值也会变化。父类中的静态方法,子类只能继承、隐藏、重载,绝对不能重写(override)。父类的final方法,子类只能继承和重载。
●Static方法隐藏也是方法名、参数、返回类型一样 ,和重写要求一样,只适用于Static方法,重写只适用于普通方法。
-
class A
-
{
-
static void a(int i) {
-
System.out.println( "A.a ");
-
}
-
}
-
-
class B extends A {
-
@Override //编译报错
-
static void a(int i) {
-
System.out.println( "B.a ");
-
}
-
}
●final也可以修饰类、方法、成员,意思是定义后就不能被改变。Final修饰类,表示终态类不能被继承。Final修饰方法时,表示终态方法,不能被覆盖(Override)。Final修饰时,表示该属性是常量。Final修饰成员变量,1、定义时赋值,2、在所有构造方法都对其赋值,两者选一。
●static定义时不必赋初值,系统赋给0,final定义时必须赋初值,接口里的成员默认是public static final的,必须在定义时赋值。方法里的变量用时得赋值。final类是指具有固定作用、标准功能的类,如Math。
●数组(包括字符串数组)的.length不用加括号,是数组的成员。字符串的.length()方法得加括号。
●一个带返回值的return语句不使用小括号"()",除非它们以某种方式使返回值更为显见。类的顺序无所谓。可以随时定义变量随时使用。
●字符串"123张艺凡"的length()是6。考试题。
●一个包就是一个文件夹。class只能被public和default,后面可接static、final(或abstract)。Protected可以修饰成员和方法,可以被不同包的子类访问,但只限于子类范围内。
子类与父类不在同一包中,此时private与friendly(default)均不能被继承(访问), protected与public可以。
●
protected与default的区别:1、protected的构造方法子类构造方法中可以通过第一句super调用,但仍然不能生成父类的引用。2、Protected的成员变量、方法会被子类继承,没被覆盖时子类父类共用,能被子类的引用访问、但该引用必须限定在该类范围内。但如果子类覆盖了父类的protected变量,则该变量为default,在本包的其他类中可以引用。继承的protected成员在非静态方法中也能用super.money的形式访问,也能直接访问。3、不同包中父类的引用(必须父类的构造方法默认或为Public)(包括在子类中)不能访问protected变量、protected方法,多态的引用也不行,即使子类重写了protected方法,编译通不过。
eg:
Father.java
-
package com.aaa;
-
public class Father
-
{
-
int height ;
-
protected int money=120;
-
public int weight;
-
protected int getMoney()
-
{
-
return money;
-
}
-
void setMoney(int newMoney)
-
{
-
money=newMoney;
-
}
-
protected void m(){
-
money=10000;
-
height=170;
-
System.out.println(money+""+height);//输出结果是10000 170
-
setMoney(300);
-
int number=getMoney();
-
System.out.println(number);
-
}
-
}
Son.java
-
package com.bbb;
-
import com.aaa.Father;
-
public class Son extends Father
-
{
-
Son()
-
{
-
m();
-
} //合法,也能调用default的变量,因为继承自父类,谁的方法调用谁的变量
-
void f()
-
{
-
money=20000;//合法
-
//height=170;//非法,height为friendly修饰的变量
-
System.out.println(money);//输出结果是20000
-
//setMoney(300); //非法
-
int number=getMoney(); //合法
-
System.out.println(number);//输出结果是20000
-
}
-
public static void main(String args[])
-
{
-
Father fa=new Father();//系统自给的构造方法是public的。Fa不能调用money变量,只能调用weight。即上文第三点。
-
fa.weight=20;
-
Son sss=new Son();
-
sss.m(); //合法
-
sss.f();//合法
-
System.out.print(sss.money); //合法
-
}
-
}
-
-
class Son2 extends Father
-
{
-
int money=100;
-
boolean str=this.money==super.money; //false
-
Son son=new Son();
-
int x=son.money;//当son中的default变量隐藏父类变量时合法,子类若没隐藏父类变量则不合法。即上文第二点。
-
}
无论在不在子类里,new出来的Parent引用都是不能调用protected的,因为此对象和父类没有任何关系。不同包的类必须是public的才能import, 类的方法和成员必须是protected才能在不同包的子类继承,才能在子类范围内调用。
●单例模式(singleton):一个类只能生成一个对象。
-
class Singleton
-
{
-
private static Singleton singleton=new Singleton();
-
private Singleton()
-
{
-
}
-
public static Singleton getInstance()
-
{
-
return singleton;
-
}
-
}
●初始化顺序:静态代码块只执行一次,实例初始化生成一个对象执行一次。
-
public class StaticTest4
-
{ public static void main(String[] args)
-
{
-
new S();
-
new S();
-
}
-
}
-
-
class P
-
{
-
{
-
System.out.println("P block");
-
}
-
static
-
{
-
System.out.println("P static block");
-
}
-
public P()
-
{
-
System.out.println("P constructor");
-
}
-
}
-
-
class Q extends P
-
{
-
{
-
System.out.println("q block");
-
}
-
static
-
{
-
System.out.println("Q static block");
-
}
-
public Q()
-
{
-
System.out.println("Q constructor");
-
}
-
}
-
-
class S extends Q
-
{
-
{
-
System.out.println("s block");
-
}
-
static
-
{
-
System.out.println("S static block");
-
}
-
public S()
-
{
-
System.out.println("S constructor");
-
}
-
}
该程序的运行结果为:
P static block
Q static block
S static block
P block
P constructor
q block
Q constructor
s block
S constructor
P block
P constructor
q block
Q constructor
s block
S constructor
即先从上到下调用所有的static静态块,且只调用一次,再调用所有父类的非静态块、构造方法,有几个对象调用几次。子类构造器执行中既没有super调用,也没有this调用,则会隐式调用父类无参数的构造器。
因此
class A
{
int m=n+2;
// static n=5; 合法,先执行static块
//int n=5 不合法,有先后顺序
}
●Javac –d . Father.java则自动为包建立目录,否则得手动建目录复制class文件。Javac –d ./com 和Javac com是等价的,都是当前目录下的com目录。执行时还得用 java com.ccc.Father,写全。
●默认导入的包只有java.lang.*,没有package的类存储在无名包内,不能导入,只能反射。但如果classpath设成了E:java,在命令台下还是能找到java目录下的class的,Jcreator找不到,eclipse也找不到(因为继承环境的默认包地址并不是E:java,而是某个src文件夹内。
●instanceof:判断左侧的操作数的引用所指的对象类型是否是右侧操作数(类或者接口)的类型。语法形式:引用名 instance of 类名(接口名),返回布尔值。
Father fa = new Son(); fa instanceof Father true
fa instanceof Son true 即fa=(Son) fa;可以
Son son = new Son(); son instanceof Father true.
Father fa2=(Father) son; //相当于Father fa2=new Son();
如果instance返回的值为true,则可以把左边的引用转变成右边的类型。
●HTML:<br>和</br>表示之间的内容固定为新的一行,即使下面没<br>也会自动换行。没</br>则下一行不会自动换行。p表示段后自动加一行空格,相当于两次br,段前没空格。
●"+"的任一端有字符串则加号是字符串连接号。Print引用值则调用Object类的toString方法,结果是类名@哈希码值,建议子类改写父类的该方法。哈希编码独一无二的代表一个对象,并且通过它能快速找到对象。
●"=="的比较:对于原生数据(8种)类型来说,比较的是左右两边的值是否相等。对于引用类型(包括String)来说,比较两边的引用的是否指向同一个对象,或者说左右两边的引用地址是否相同。
●String str1="bbb"; String str3=new String("bbb");
String str2="bbb"; String str4=new String("bbb");
Print(str1==str2); 答案是true. Print(str3==str4);答案False、
●public boolean equals(Object obj)
{return (this == obj) ; }
即判断调用equals()方法的引用与传进来的引用是否指向同一个对象。
对于Object类的equals方法来说,它等价于==。
而String类改写了equals方法,它是判断当前字符串与传进来的字符串是否内容一致。 Str3.equals(str4)为true。对于String对象的相等性判断来说,请使用equals()方法,而不使用==。
●String类是常量,其对象一旦创建完毕就无法改变。当使用+拼接字符串时,会生成新的字符串对象,而不是向原有的字符串对象追加内容。
●String Pool,在栈中。
String s="aaa".采用字面值方式赋值时,首先检查池中是否有该字符串,有则不新建,直接指向它。如果没有则在池中创建该对象并引用。
String s=new String("aaa");不管池中有没有该字符串,都在堆中创建该字符串对象并引用指向它。池中没有还要在池中创建该对象。
使用New都会在堆中创建对象。
●String类的Intern方法总是返回池中的引用。Class A中有个成员变量String s;则A a = new A(); 此时a.s是一个String类的引用,可以使用String类的任何方法。System.out.println("abc".toString());也可以。与之类似,System.out.println(new Integer(4).equals(4));
●String类:
返回值 方法名(参数)
Int compareTo(串);字母大的为大,大返回一个正数,相等返回0,小返回一个负数。(值为第一个不同字符位置两个字符的差值Unicode,若全部字符相同则返回长度之差)。类似的是compareToIgnoreCase。
Int indexOf(串) 返回子串在串中首次出现的索引值,没有返回-1
Int indexOf(int) int为字符的Unicode值,没有此字符返回-1
Int lastIndexOf(串或int) 子串最右边出现的索引值
上述三个index方法还能加第二个参量int,表示从此索引开始找。此索引超过字符串长度并不检查,故返回-1。
Boolean contains(串) 只有完整包含串时返回true.
Boolean contentEquals(串) 等价于方法equals,内容完全相等时返回true.
String toUpperCase();
String toLowerCase();
String valueOf(基本类型|字符数组|引用) 引用是调用该类的toString方法,字符数组是将之转换成完整的字符串。定义字符数组用单引号。字符数组的toString方法没有改写,也是类名@hashcode。但直接只打印字符数组的引用却不是调用toString方法,而是打出串来。
String substring(起始索引,结束索引有没有都行) 返回该串的子串
char[] toCharArray() 字符串转换成字符数组
String replace(子串,新子串) 将原子串替换成新子串,并返回新字符串的引用,原串不受影响。如没有该子串则返回此对象的引用。
String replaceFirst(正则表达式,新子串) 将符合正则表达式的字符替换为新子串。正则表达式格式为 "[abc && def]"
与之相似 replaceAll
String trim() 修建,修理。去掉字符串的前导和后导空白,并返回新对象的引用。如果没有空白或前后字符都大于unicode20(表示空白字符),则返回该串的引用。