黑马程序员——面向对象(2)
2012-07-20 01:42
232 查看
-----------
android培训、java培训、java学习型技术博客、期待与您交流!
------------
十一、封装 encapsulation
1、将一类事物的特征和行为封装在一个类中,定义为成员变量和成员方法。类中的成员函数可以访问自己的成员变量。
2、为了实现良好的封装,可以用private关键字将成员变量私有化,对外提供
一个public型的set、get方法对成员变量赋值、获取成员变量的值。
例如:
class Person {
privateString name;
privateint age;
publicvoid setName(String name) {
this.name= name;
}
publicString getName() {
returnname;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
十二、继承inherit
用extends关键字
1、特点
只支持单继承,不支持多继承。支持多重继承
一个类可以有多个子类,只能有一个父类。
加载类的时候先加载父类。
一个了如果没有声明父类,则默认继承Object类。
2、子类对象创建的过程
子类对象之所以能调用父类的方法,是因为在创建子类对象的时候,其内部创建了一个父类对象。调用子类方法时,JVM会现在子类中查找是否包含该方法,如果没有则找父类。
在调用子类构造函数的时候,一定会先使用”super(参数)”形式调用父类的构造函数创建父类对象。如果是调用父类无参的构造函数,可以不写super(),如果调用父类有参数的构造函数,必须写 super(参数)。
构造函数的第一条语句要么是this,要么是super,二者选其一。如果没写,则默认是super()。
3、向上转型
子类对象可以当父类对象使用。 Fruit f = new Apple();
如果一个方法要求传入一个父类类型的对象,我们也可以传入一个子类对象。
子类对象当做父类来用时,不能调用子类特有的成员。编译时语法检查报错。
子类对象当做父类来用时,用父类类型的变量调用方法时,先找子类的方法(java的动态分配机制);如果调用变量则找父类的。
创建的是哪个类的对象,调用方法时就先在哪个类中找(与变量类型无关)。
4、强制类型装换
将向上转型成父类的子类对象强转回子类对象。无论类型是否匹配,编译时都不会报错。语法:“(父类类型)对象的引用变量;”
强转之前进行类型判断:if(f instanceof Apple){ Apple a= (Apple) f;}
5、子类重写(Override)父类的方法
重写父类方法时,返回值类型、参数列表必须完全一致。
重写父类方法时,不能定义更低的访问权限。
public > protected > default > private
重写父类方法时,不能抛出更多的异常。
一个方法在重写父类方法后,若要调用被覆盖的方法,使用“super.方法名”。
可以在方法前加@Override检查重写是否成功。
十三、多态polymorphism
一段代码可以运行出多种形态。用父类的引用指向多个子类的对象。
多态的前提是类与类之间有关系,要么有继承、要么实现,通常还要实现方法的覆盖。
将函数的形参定义为父类类型,所有的子类都可以传入,这时我们可以将一个子类对象作为实参传递过去,此时方法定义的形参为父类,在方法中使用父类变量调用方法时,其实是调用子类的方法(在把子类当做父类来用时,使用父类变量访问方法,访问的是子类的方法,因为虚拟机会找到变量引用的地址,根据这个地址来访问方法,这叫动态分配)——向后兼容。可以提高代码的复用性。
(1)定义一个类,其中的方法形参为父类
class Juicer {
publicvoid run(Fruit fruit) {
fruit.squeeze();
}
}
(2)定义一个父类
class Fruit {
public void squeeze() {}
}
(3)子类重写父类的方法
class Apple extends Fruit {
public voidsqueeze() {
System.out.println(“榨出一杯苹果汁”)
}
}
(4)主函数中调用时传入子类对象,调用子类的方法:
new Juicer().run(newApple());
十四、抽象类
1、概念
用abstract class修饰的类就是抽象类。
抽象类中可以定义抽象方法(用abstract修饰的方法)。
2、应用情景
在定义类时如果多个类有相同的方法,那么就把这些方法抽取到父类中定义。完全相同的方法直接在父类中定义并实现,如果只有方法签名一样而实现代码不同,那么就可以在父类中定义抽象方法。这样在看到父类的时候就知道子类都有什么功能了。
3、注意
(1)有抽象方法的类必须声明为抽象类,抽象类不可以用new创建对象,因为调用抽象方法没意义,没有实现,不能运行;
(2)抽象类可以没有抽象方法,目的就是为了不能创建对象;
(3)抽象类不能创建对象,就是用来表示子类有哪些方法的,是为了支持多态(将子类对象当做父类来用,可以调到子类的方法);
(4)子类继承抽象类是必须重写所有的抽象方法。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类;
(5)抽象类中的抽象方法要被使用,必须由子类重写起所有的抽象方法,建立子类对象调用。
4、抽象类和一般类比较
(1)抽象类和一般类没有太大区别:如何描述事物,就如何描述事物,只不过该事物出现了一些不确定的部分。也就是该事物的功能需要明确出现,但是无法
4000
定义主体,通过抽象方法来表示;
(2)抽象类比一般类多了一个抽象方法;
(3)抽象类不可以实例化。
十五、接口interface
****
十六、内部类
1、类中的内部类:
(1)概念
在类的级别下定义的类,内部类也是外部类的一个成员。
内部类必须先创建外部对象才能创建对象。
语法:外部类名.内部类名 变量名=new 外部类名().new 内部类名();
(2)内部类访问外部类的成员(私有的和公有的)
语法:外部类名.this.成员名——其中,“外部类名.this”代表调用当前方法的内部类对象的外部类对象
方法中、内部类中、外部类中的变量重名时,直接使用变量名访问的是方法
中的变量(不会自动初始化,使用前需初始化),使用“this.变量名”访问的是内部类的成员变量,使用“外部类名.this.成员名”访问的是外部类的成员变量。
(3)使用情景
在定义一个类的时候,如果需要访问当前类的私有成员,则可定义成当前类的内部类。
(4)注意事项
a.外部类不能访问内部类的成员。原因:一、作用域;二、对象的生命周期(创建外部类对象的时候不一定有内部类对象,创建内部类对象的时候一定有外部类对象)。
b.内部类生成的.class文件名是“外部类名$内部类名.class”
2、方法中的内部类
(1)只能在当前方法中使用。访问外部类的成员变量:外部类名.this.内部类名。
使用方法中的内部类和普通的内中的内部类相同。
(2)应用情景:
如果一个类只在某个方法中使用,就可以定义为方法中的内部类。
(3)注意事项:
a.方法中的内部类不能访问方法中定义的局部变量,除非将变量声明为final型的。原因:方法中定义的局部变量在方法运行结束后就被销毁,生命周期结束;而对象则在方法运行结束后不一定销毁,只有没有引用指向时才结束。
因此,内部类访问方法中的局部变量时,必须把变量声明为final型的。
b.编译生成的.class文件名为“外部类名$编号 内部类名.class”
——匿名内部类:方法中内部类的一种。可以继承一个类,也可以实现接口。
语法:new 父类名/接口名(){ 类定义 } ——声明指定类的子类,用这个子类创建一个对象
编译生成的.class文件名为“外部类名$编号.class”
如果一个类只使用一次,就可以定义为匿名内部类。
3、静态内部类
在非静态的内部类中不能声明静态的成员。
(1)特点
a.不用创建外部类对象就能直接创建内部类对象,可以定义静态成员。
语法:外部类名.内部类名 变量名 = new 外部类名.内部类名();
b.不能访问外部类的非静态成员
c.在静态内部类中访问外部类的静态成员:外部类名.外部静态成员名
d.不能使用“外部类名.this”
(2)应用场景:
如果定义一个类时,不需要访问外部类的非静态成员,就可以定义为静态内部类。如果需要定义静态成员,只能声明为静态的。
十七、包 package
总结:写所有的类都要带包,第一条语句写package;
写public类时和文件名同名;
导入的时候用类名:import 包名.类名
编译时用 –d;
运行时带包名。
1、定义包
package xxx;——必须为java源文件的第一条语句。包名全部小写,用分号隔开,通常是“公司域名.项目名.功能层”.
如果一个类中没有package语句,这个类为缺省无包名。
2、编译执行带包的java文件
编译:javac -d <目录> 源文件名.java 例如:javac –d . MyJava.java
执行:java 包名.类名 例如:java cn.itcast.MyJava
3、导入不同包中的类:
被导入的类必须是public型的,否则不能在不同的包中使用。公有类的类名必须和文件名相同。一个文件中只能写一个公有类。
(1)import 包名.*;——在用类名访问指定的类时,会现在当前包中查找是否有这个类,如果没有才会到导入的包中查找。
(2)import 包名.类名;——在用类名访问指定的类的时候,无论当前包中是否有这个类,都会找指定的包。
(3)全限定名:包名.类名——如果需要访问不同包中两个同名的类,那么在写类名的时候可以直接写全限定名。
4、有包的类和无包的类的相互访问
有包的类可以访问有包的类,无包的类可以访问无包的类。
无包的类可以访问有包的类,直接导入即可。
有包的类不可以访问无包的类。直接使用类名是在当前的包中查找,而当前包中没有无包的类,且无法导入包。
5、jar文件
(1)概念:
java文件的压缩格式。通常将软件中若干个.class文件打成一个jar文件。
(2)打jar包:jar cvf <归档文件名>文件名1 文件名2 文件(夹)名3;
更新jar包:jar uvf <归档文件名>文件名;
例如:jar cvfclasses.jar A.class B.class;
jar uvf classes.jar C;
(3)使用jar包中的类:
将jar包的绝对路径配到classpath中。
例如:set classpath=E:\classes.jar;.(如果不加. jvm只找jar包,不找当前目录)。
(4)运行jar包:
在META-INF文件夹中找到MINIFEST.MF文件;
在文件中指定Main-Class属性,指定要运行的类;
例如:Main-Class: cn.itcast.MyJava;
运行命令:java –jarjar文件名 例如:java –jar MyJava.jar;
十八、异常
1、概念:程序运行过程中抛出的一些错误。
2、分类:见下图
3、抛出异常
用throw关键字抛出异常对象。throw new RuntimeException(“出错了”);
程序中一旦出现异常,下面的代码就不会再执行了。
如果抛出的是RuntimeException,那么调用当前方法的代码可以不处理;否则,调用处必须处理异常。
4、处理异常
(1)在当前方法签名处用throws声明,表明当前方法也有可能抛出异常;
(2)try {
可能出现异常的代码
} catch(Exception e){
e.printStackTrace(); // 打印异常信息
}
5、Finally代码块
和try配合使用,只要执行了try中的代码,无论如何都会执行finally中的代码,除非使用System.exit(0)推出java虚拟机,这样做不会执行finally。
try{ 可能出现异常的代码 } Finally{ 无论如何都会执行的代码 }
6、自定义异常
如果要定义一个编译时异常, 可以定义类继承Exception,然后创建对象, 用throw关键字抛出即可。
如果要定义一个运行时异常, 那么就定义类继承RuntimeException。
例1:class MyExceptionextends Exception{ }
例2:class MyExceptionextends RuntimeException{
publicMyException(){ }
publicMyException(String msg) {
super(msg);
}
}
调用父类的构造函数,打印出异常信息:出错
7、注意:
(1)子类重写父类的方法时不能抛出更多的异常;
(2)处理多个异常的方法:
a.throws 异常1,异常2
b.try{可能出现异常的代码} catch(ClassNotFoundException e){ … }
只会执行一个catch catch(FileNotFoundException e){ …}
catch( Exception e ){ …}
父类异常,不要写在子类上面,否则会报错
3、try与finally嵌套
try{
可能出现异常的代码
} Finally{ try{ 可能出现异常的代码 }
Finally{ 无论如何都会执行的代码 }
}
十九、访问权限
二十、Object类:
Object类是java中所有类的父类。定义一个类,若没有继承任何类,默认继承object类。
1、finalize方法
Object类定义了一个finalize()方法,所以的类都会有这个方法。任何对象在成为垃圾被销毁之前,会自动调用finalize()方法。
虚拟机中的垃圾对象不会马上被回收。当对象堆积到一定程度时才会被回收。如果我们希望清空所有的垃圾,就可以调用System.gc();
System.gc(); // 清理虚拟机中的所有垃圾对象,异步方法(这个方法会开启一个新的线程,即使没有执行完下面的代码也能继续执行)。销毁垃圾需要时间。
Thread.sleep(3000); // 程序休眠3000毫秒
Object类中的finalize方法是空的,什么代码都没有。我们在定义个一个类的时候,希望这个类的对象在被销毁之前执行某段代码,就可以在类中重写finalize方法。
例如:
@Override
protected void finalize() {
System.out.println(“对象被回收”);
}
2、toString方法:
将对象转为字符串表示形式。Object类中toString方法返回“类名@地址“。
调用print或println方法打印对象时,方法内部会自动调用toString方法,打印出这个对象的字符串形式。所以System.out.println(newPerson().toString)与System.out.println(new Person())的结果一样,都是“类名@地址”。但是由于String类重写了toString方法,所以System.out.println(new String(“abc”))打印出的是abc。
当希望调用toString方法返回成员变量的值,而不是返回地址时,就可以重写该方法。
例如:
@Override
public String toString {
return name + “,” + age;
}
3、equals方法:
比较两个对象的是否相同。Object类中的equals默认比较的是对象的地址。
由于String类重写了Object类的equals方法,比较的是两个字符串的内容是否完全一样。比较两个字符串的内容是否相同时,应用equals方法。如果使用 == 则比较的是地址。
在定义类的时候,如果希望这个类的对象可以按照属性比较,而不是比较对象的地址,那么就应该重写equals方法,在方法内比较所有的属性。
例如:
@Override
public boolean equals(Object obj) {
if(this== obj) // 如果地址相同,返回true,为了提高效率。
returntrue;
if(!(objinstanceof Person)) // 如果obj不是Person类型返回false
returnfalse;
Personother = (Person) obj; //由于要使用子类特有的成员,将object强转回Person
if(this.name== null) { // 如果自己的名字为空,对方名字不
是空,返回false,避免空指针异常
if(other.name!= null)
returnflase;
} else if(!this.name.equals(other.name))
//调用String类的equals()方法
returnfalse;
if(this.age!= other.age)
returnflase;
returntrue;
}
二十一、文档注释:
生成文档注释的类必须是public型的,因此文件名和类名也一样。
生成文档注释的命令: javadoc –d (目录) –version –author (源文件)
1、类的注释:写在定义类之前
/**
* 这是一个用来描述人的类
* @author 作者姓名 ————作者信息
* @version 版本信息 ————版本信息
*/
2、方法的注释:写在定义方法之前
/*
* @param 参数名 ————参数信息说明
* @return ————返回值说明
*/
二十二、main()方法的语法
public 代表当前方法是公用的,所有的类都可以调到,为了让虚拟机可以调用。
static 代表当前方法时静态的,不用创建对象就可调用,方便虚拟机可以直接调用到。
void 代表该方法没有返回值,这个方法时虚拟机调用的,没有返回值。
main方法的名字, 启动虚拟机后, 虚拟机会自动找这个方法。
(String [] args) 参数列表, 启动程序时可以传入若干字符串, 虚拟机在调用main函数的时候会传进来。
二十三、创建对象时内存中的工作顺序
Person p = new Person();
(1)在栈内存中开辟一块空间,存放变量p;
(2)jvm会读取指定路径下的person.class文件,并加载进内存。
如果有直接的父类先加载父类;
(类在第一次使用的时候被加载:如创建对象,使用静态变量,使用静态方法。)
(3)将类中的静态成员放入静态区域,默认初始化(引用数据类型为null,基本数据类型为0),执行静态成员代码块。
(4)调用构造函数创建对象,在堆内存中开辟空间,分配地址给创建的对象new Person(),将普通成员变量进行默认初始化(引用数据类型为null,基本数据类型为0);
(如果构造方法中显式或隐式地用super调用父类的构造函数,则先执行父类的构造函数。)
(5)在类中,成员代码块与成员变量赋值语句之前按照从上到下的顺序执行,哪个在前面就先执行哪个;
(6)执行该类的构造函数中的代码;
(7)将变量p指向对象的地址。
-----------
android培训、java培训、java学习型技术博客、期待与您交流!
------------
android培训、java培训、java学习型技术博客、期待与您交流!
------------
十一、封装 encapsulation
1、将一类事物的特征和行为封装在一个类中,定义为成员变量和成员方法。类中的成员函数可以访问自己的成员变量。
2、为了实现良好的封装,可以用private关键字将成员变量私有化,对外提供
一个public型的set、get方法对成员变量赋值、获取成员变量的值。
例如:
class Person {
privateString name;
privateint age;
publicvoid setName(String name) {
this.name= name;
}
publicString getName() {
returnname;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
十二、继承inherit
用extends关键字
1、特点
只支持单继承,不支持多继承。支持多重继承
一个类可以有多个子类,只能有一个父类。
加载类的时候先加载父类。
一个了如果没有声明父类,则默认继承Object类。
2、子类对象创建的过程
子类对象之所以能调用父类的方法,是因为在创建子类对象的时候,其内部创建了一个父类对象。调用子类方法时,JVM会现在子类中查找是否包含该方法,如果没有则找父类。
在调用子类构造函数的时候,一定会先使用”super(参数)”形式调用父类的构造函数创建父类对象。如果是调用父类无参的构造函数,可以不写super(),如果调用父类有参数的构造函数,必须写 super(参数)。
构造函数的第一条语句要么是this,要么是super,二者选其一。如果没写,则默认是super()。
3、向上转型
子类对象可以当父类对象使用。 Fruit f = new Apple();
如果一个方法要求传入一个父类类型的对象,我们也可以传入一个子类对象。
子类对象当做父类来用时,不能调用子类特有的成员。编译时语法检查报错。
子类对象当做父类来用时,用父类类型的变量调用方法时,先找子类的方法(java的动态分配机制);如果调用变量则找父类的。
创建的是哪个类的对象,调用方法时就先在哪个类中找(与变量类型无关)。
4、强制类型装换
将向上转型成父类的子类对象强转回子类对象。无论类型是否匹配,编译时都不会报错。语法:“(父类类型)对象的引用变量;”
强转之前进行类型判断:if(f instanceof Apple){ Apple a= (Apple) f;}
5、子类重写(Override)父类的方法
重写父类方法时,返回值类型、参数列表必须完全一致。
重写父类方法时,不能定义更低的访问权限。
public > protected > default > private
重写父类方法时,不能抛出更多的异常。
一个方法在重写父类方法后,若要调用被覆盖的方法,使用“super.方法名”。
可以在方法前加@Override检查重写是否成功。
十三、多态polymorphism
一段代码可以运行出多种形态。用父类的引用指向多个子类的对象。
多态的前提是类与类之间有关系,要么有继承、要么实现,通常还要实现方法的覆盖。
将函数的形参定义为父类类型,所有的子类都可以传入,这时我们可以将一个子类对象作为实参传递过去,此时方法定义的形参为父类,在方法中使用父类变量调用方法时,其实是调用子类的方法(在把子类当做父类来用时,使用父类变量访问方法,访问的是子类的方法,因为虚拟机会找到变量引用的地址,根据这个地址来访问方法,这叫动态分配)——向后兼容。可以提高代码的复用性。
(1)定义一个类,其中的方法形参为父类
class Juicer {
publicvoid run(Fruit fruit) {
fruit.squeeze();
}
}
(2)定义一个父类
class Fruit {
public void squeeze() {}
}
(3)子类重写父类的方法
class Apple extends Fruit {
public voidsqueeze() {
System.out.println(“榨出一杯苹果汁”)
}
}
(4)主函数中调用时传入子类对象,调用子类的方法:
new Juicer().run(newApple());
十四、抽象类
1、概念
用abstract class修饰的类就是抽象类。
抽象类中可以定义抽象方法(用abstract修饰的方法)。
2、应用情景
在定义类时如果多个类有相同的方法,那么就把这些方法抽取到父类中定义。完全相同的方法直接在父类中定义并实现,如果只有方法签名一样而实现代码不同,那么就可以在父类中定义抽象方法。这样在看到父类的时候就知道子类都有什么功能了。
3、注意
(1)有抽象方法的类必须声明为抽象类,抽象类不可以用new创建对象,因为调用抽象方法没意义,没有实现,不能运行;
(2)抽象类可以没有抽象方法,目的就是为了不能创建对象;
(3)抽象类不能创建对象,就是用来表示子类有哪些方法的,是为了支持多态(将子类对象当做父类来用,可以调到子类的方法);
(4)子类继承抽象类是必须重写所有的抽象方法。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类;
(5)抽象类中的抽象方法要被使用,必须由子类重写起所有的抽象方法,建立子类对象调用。
4、抽象类和一般类比较
(1)抽象类和一般类没有太大区别:如何描述事物,就如何描述事物,只不过该事物出现了一些不确定的部分。也就是该事物的功能需要明确出现,但是无法
4000
定义主体,通过抽象方法来表示;
(2)抽象类比一般类多了一个抽象方法;
(3)抽象类不可以实例化。
十五、接口interface
****
抽象类 | 接口 |
可以有抽象方法,可以有不抽象的方法 | 所有的方法都是抽象的 |
子类用extends继承 | 子类用implements实现 |
成员方法没有默认修饰符 | 成员方法默认public abstract修饰 |
成员变量没有默认修饰符 | 成员变量默认是public static final |
抽象类可以继承(extends)抽象类,抽象类不能继承接口 | 接口可以继承(extends)接口, 接口不能继承抽象类 |
一个类智能继承一个抽象类 | 一个类可以实现多个接口 |
能用接口的时候就不用抽象类。原因:接口不占用继承的位置,一个类可以同时继承一个类实现多个接口(extends在implements之前)。、 如果需要定义不抽象的方法则只能使用抽象类。 |
1、类中的内部类:
(1)概念
在类的级别下定义的类,内部类也是外部类的一个成员。
内部类必须先创建外部对象才能创建对象。
语法:外部类名.内部类名 变量名=new 外部类名().new 内部类名();
(2)内部类访问外部类的成员(私有的和公有的)
语法:外部类名.this.成员名——其中,“外部类名.this”代表调用当前方法的内部类对象的外部类对象
方法中、内部类中、外部类中的变量重名时,直接使用变量名访问的是方法
中的变量(不会自动初始化,使用前需初始化),使用“this.变量名”访问的是内部类的成员变量,使用“外部类名.this.成员名”访问的是外部类的成员变量。
(3)使用情景
在定义一个类的时候,如果需要访问当前类的私有成员,则可定义成当前类的内部类。
(4)注意事项
a.外部类不能访问内部类的成员。原因:一、作用域;二、对象的生命周期(创建外部类对象的时候不一定有内部类对象,创建内部类对象的时候一定有外部类对象)。
b.内部类生成的.class文件名是“外部类名$内部类名.class”
2、方法中的内部类
(1)只能在当前方法中使用。访问外部类的成员变量:外部类名.this.内部类名。
使用方法中的内部类和普通的内中的内部类相同。
(2)应用情景:
如果一个类只在某个方法中使用,就可以定义为方法中的内部类。
(3)注意事项:
a.方法中的内部类不能访问方法中定义的局部变量,除非将变量声明为final型的。原因:方法中定义的局部变量在方法运行结束后就被销毁,生命周期结束;而对象则在方法运行结束后不一定销毁,只有没有引用指向时才结束。
因此,内部类访问方法中的局部变量时,必须把变量声明为final型的。
b.编译生成的.class文件名为“外部类名$编号 内部类名.class”
——匿名内部类:方法中内部类的一种。可以继承一个类,也可以实现接口。
语法:new 父类名/接口名(){ 类定义 } ——声明指定类的子类,用这个子类创建一个对象
编译生成的.class文件名为“外部类名$编号.class”
如果一个类只使用一次,就可以定义为匿名内部类。
3、静态内部类
在非静态的内部类中不能声明静态的成员。
(1)特点
a.不用创建外部类对象就能直接创建内部类对象,可以定义静态成员。
语法:外部类名.内部类名 变量名 = new 外部类名.内部类名();
b.不能访问外部类的非静态成员
c.在静态内部类中访问外部类的静态成员:外部类名.外部静态成员名
d.不能使用“外部类名.this”
(2)应用场景:
如果定义一个类时,不需要访问外部类的非静态成员,就可以定义为静态内部类。如果需要定义静态成员,只能声明为静态的。
十七、包 package
总结:写所有的类都要带包,第一条语句写package;
写public类时和文件名同名;
导入的时候用类名:import 包名.类名
编译时用 –d;
运行时带包名。
1、定义包
package xxx;——必须为java源文件的第一条语句。包名全部小写,用分号隔开,通常是“公司域名.项目名.功能层”.
如果一个类中没有package语句,这个类为缺省无包名。
2、编译执行带包的java文件
编译:javac -d <目录> 源文件名.java 例如:javac –d . MyJava.java
执行:java 包名.类名 例如:java cn.itcast.MyJava
3、导入不同包中的类:
被导入的类必须是public型的,否则不能在不同的包中使用。公有类的类名必须和文件名相同。一个文件中只能写一个公有类。
(1)import 包名.*;——在用类名访问指定的类时,会现在当前包中查找是否有这个类,如果没有才会到导入的包中查找。
(2)import 包名.类名;——在用类名访问指定的类的时候,无论当前包中是否有这个类,都会找指定的包。
(3)全限定名:包名.类名——如果需要访问不同包中两个同名的类,那么在写类名的时候可以直接写全限定名。
4、有包的类和无包的类的相互访问
有包的类可以访问有包的类,无包的类可以访问无包的类。
无包的类可以访问有包的类,直接导入即可。
有包的类不可以访问无包的类。直接使用类名是在当前的包中查找,而当前包中没有无包的类,且无法导入包。
5、jar文件
(1)概念:
java文件的压缩格式。通常将软件中若干个.class文件打成一个jar文件。
(2)打jar包:jar cvf <归档文件名>文件名1 文件名2 文件(夹)名3;
更新jar包:jar uvf <归档文件名>文件名;
例如:jar cvfclasses.jar A.class B.class;
jar uvf classes.jar C;
(3)使用jar包中的类:
将jar包的绝对路径配到classpath中。
例如:set classpath=E:\classes.jar;.(如果不加. jvm只找jar包,不找当前目录)。
(4)运行jar包:
在META-INF文件夹中找到MINIFEST.MF文件;
在文件中指定Main-Class属性,指定要运行的类;
例如:Main-Class: cn.itcast.MyJava;
运行命令:java –jarjar文件名 例如:java –jar MyJava.jar;
十八、异常
1、概念:程序运行过程中抛出的一些错误。
2、分类:见下图
3、抛出异常
用throw关键字抛出异常对象。throw new RuntimeException(“出错了”);
程序中一旦出现异常,下面的代码就不会再执行了。
如果抛出的是RuntimeException,那么调用当前方法的代码可以不处理;否则,调用处必须处理异常。
Throwable:所有错误或异常的超类 |
错误(error):由java虚拟机生成并抛出 |
异常(Exception) |
编译时异常:Exception中除了运行时异常的部分,在编译之前必须对代码中的异常进行处理 |
运行时异常(RuntimeException的子类):在编译之前可以不进行处理。如:空指针异常、算数异常等 |
4、处理异常
(1)在当前方法签名处用throws声明,表明当前方法也有可能抛出异常;
(2)try {
可能出现异常的代码
} catch(Exception e){
e.printStackTrace(); // 打印异常信息
}
5、Finally代码块
和try配合使用,只要执行了try中的代码,无论如何都会执行finally中的代码,除非使用System.exit(0)推出java虚拟机,这样做不会执行finally。
try{ 可能出现异常的代码 } Finally{ 无论如何都会执行的代码 }
6、自定义异常
如果要定义一个编译时异常, 可以定义类继承Exception,然后创建对象, 用throw关键字抛出即可。
如果要定义一个运行时异常, 那么就定义类继承RuntimeException。
例1:class MyExceptionextends Exception{ }
例2:class MyExceptionextends RuntimeException{
publicMyException(){ }
//若不定义有参数的构造函数,抛出异常时不能传入异常信息。 throw new Myexception(“出错”); |
super(msg);
}
}
调用父类的构造函数,打印出异常信息:出错
7、注意:
(1)子类重写父类的方法时不能抛出更多的异常;
(2)处理多个异常的方法:
a.throws 异常1,异常2
b.try{可能出现异常的代码} catch(ClassNotFoundException e){ … }
只会执行一个catch catch(FileNotFoundException e){ …}
catch( Exception e ){ …}
父类异常,不要写在子类上面,否则会报错
3、try与finally嵌套
try{
可能出现异常的代码
} Finally{ try{ 可能出现异常的代码 }
Finally{ 无论如何都会执行的代码 }
}
十九、访问权限
| private | default | protected | Public |
同一个类中 | √ | √ | √ | √ |
同个包中的类 | | √ | √ | √ |
子类 | | | √ | √ |
其他包中的类 | | | | √ |
二十、Object类:
Object类是java中所有类的父类。定义一个类,若没有继承任何类,默认继承object类。
1、finalize方法
Object类定义了一个finalize()方法,所以的类都会有这个方法。任何对象在成为垃圾被销毁之前,会自动调用finalize()方法。
虚拟机中的垃圾对象不会马上被回收。当对象堆积到一定程度时才会被回收。如果我们希望清空所有的垃圾,就可以调用System.gc();
System.gc(); // 清理虚拟机中的所有垃圾对象,异步方法(这个方法会开启一个新的线程,即使没有执行完下面的代码也能继续执行)。销毁垃圾需要时间。
Thread.sleep(3000); // 程序休眠3000毫秒
Object类中的finalize方法是空的,什么代码都没有。我们在定义个一个类的时候,希望这个类的对象在被销毁之前执行某段代码,就可以在类中重写finalize方法。
例如:
@Override
protected void finalize() {
System.out.println(“对象被回收”);
}
2、toString方法:
将对象转为字符串表示形式。Object类中toString方法返回“类名@地址“。
调用print或println方法打印对象时,方法内部会自动调用toString方法,打印出这个对象的字符串形式。所以System.out.println(newPerson().toString)与System.out.println(new Person())的结果一样,都是“类名@地址”。但是由于String类重写了toString方法,所以System.out.println(new String(“abc”))打印出的是abc。
当希望调用toString方法返回成员变量的值,而不是返回地址时,就可以重写该方法。
例如:
@Override
public String toString {
return name + “,” + age;
}
3、equals方法:
比较两个对象的是否相同。Object类中的equals默认比较的是对象的地址。
由于String类重写了Object类的equals方法,比较的是两个字符串的内容是否完全一样。比较两个字符串的内容是否相同时,应用equals方法。如果使用 == 则比较的是地址。
在定义类的时候,如果希望这个类的对象可以按照属性比较,而不是比较对象的地址,那么就应该重写equals方法,在方法内比较所有的属性。
例如:
@Override
public boolean equals(Object obj) {
if(this== obj) // 如果地址相同,返回true,为了提高效率。
returntrue;
if(!(objinstanceof Person)) // 如果obj不是Person类型返回false
returnfalse;
Personother = (Person) obj; //由于要使用子类特有的成员,将object强转回Person
if(this.name== null) { // 如果自己的名字为空,对方名字不
是空,返回false,避免空指针异常
if(other.name!= null)
returnflase;
} else if(!this.name.equals(other.name))
//调用String类的equals()方法
returnfalse;
if(this.age!= other.age)
returnflase;
returntrue;
}
二十一、文档注释:
生成文档注释的类必须是public型的,因此文件名和类名也一样。
生成文档注释的命令: javadoc –d (目录) –version –author (源文件)
1、类的注释:写在定义类之前
/**
* 这是一个用来描述人的类
* @author 作者姓名 ————作者信息
* @version 版本信息 ————版本信息
*/
2、方法的注释:写在定义方法之前
/*
* @param 参数名 ————参数信息说明
* @return ————返回值说明
*/
二十二、main()方法的语法
public 代表当前方法是公用的,所有的类都可以调到,为了让虚拟机可以调用。
static 代表当前方法时静态的,不用创建对象就可调用,方便虚拟机可以直接调用到。
void 代表该方法没有返回值,这个方法时虚拟机调用的,没有返回值。
main方法的名字, 启动虚拟机后, 虚拟机会自动找这个方法。
(String [] args) 参数列表, 启动程序时可以传入若干字符串, 虚拟机在调用main函数的时候会传进来。
二十三、创建对象时内存中的工作顺序
Person p = new Person();
(1)在栈内存中开辟一块空间,存放变量p;
(2)jvm会读取指定路径下的person.class文件,并加载进内存。
如果有直接的父类先加载父类;
(类在第一次使用的时候被加载:如创建对象,使用静态变量,使用静态方法。)
(3)将类中的静态成员放入静态区域,默认初始化(引用数据类型为null,基本数据类型为0),执行静态成员代码块。
(4)调用构造函数创建对象,在堆内存中开辟空间,分配地址给创建的对象new Person(),将普通成员变量进行默认初始化(引用数据类型为null,基本数据类型为0);
(如果构造方法中显式或隐式地用super调用父类的构造函数,则先执行父类的构造函数。)
(5)在类中,成员代码块与成员变量赋值语句之前按照从上到下的顺序执行,哪个在前面就先执行哪个;
(6)执行该类的构造函数中的代码;
(7)将变量p指向对象的地址。
-----------
android培训、java培训、java学习型技术博客、期待与您交流!
------------
相关文章推荐
- 黑马程序员-------面向对象-------
- 黑马程序员_笔迹七_面向对象(高级)---接口
- 黑马程序员<java基础<面向对象(封装,继承,多态,抽象)>>
- 黑马程序员-java学习日志之面向对象
- 黑马程序员---java基础之面向对象(二)
- 黑马程序员+第三章面向对象 第07天
- 黑马程序员--面向对象--1st day
- 黑马程序员----Java基础之面向对象(封装 继承 多态)
- 黑马程序员------毕老师视频笔记第十天------面向对象(包)
- 黑马程序员——面向对象5:this关键字
- 黑马程序员----Java基础之面向对象(最终篇)
- 黑马程序员——java基础——面向对象的多态
- 黑马程序员------面向对象
- 黑马程序员--Java基础语法之面向对象
- 黑马程序员—面向对象(下)
- 黑马程序员---------Java面向对象——网络编程
- 黑马程序员 Java 面向对象三
- 黑马程序员-java学习之面向对象(类与对象的关系)
- 黑马程序员---面向对象(一)
- 黑马程序员---------Java面向对象——注解