-------android培训、java培训、java学习型技术博客、期待与您交流! ------------
1.抽象类
抽象定义:
抽象就是从多个事物中将共性的,本质的内容抽取出来。例如:狼和狗的共性都是犬科,犬科就是抽象出来的概念。
抽象类:
java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。
抽象方法的由来:
多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。
例如:狼和狗都有吼叫的方法,可以吼叫的内容是不一样的,所以抽取出来的犬科虽然有吼叫功能,但是并不明确吼叫的细节。
抽象类的特点:
1.抽象类和抽象方法必须用abstract关键字来修饰。
2.抽象方法只有方法声明,没有方法体,定义在抽象类中。
格式:修饰符 abstract 返回值类型 函数名(参数列表);
3.抽象类不可以被实例化,也就是不可以用new创建对象。原因如下:
抽象类是具体事物抽取出来的,本身是不具体的,没有对应的实例,例如:犬科是一个抽象的概念,真正存在的是儿狼和狗。而且抽象类即使创建了对象,调用抽象方法也没有意义。
4.抽象类通过其子类实例化,而子类需要覆盖掉抽象类中所有的抽象方法后才可以创建对象,否则子类也是抽象类。
基本抽象类代码:
abstrack class Student//抽象类
{
abstrack void study();//抽象方法
}
class BaseStudent extends Student//继承抽象类
{
void study()//覆盖父类方法
{
System.out.prinln("base study");
}
}
class AdvStudent extends Student//继承抽象类
{
void study()//覆盖父类方法
{
System.out.println("Adv study");
}
}
class AbstrackDemo
{
public static void main(String[] args)
{
System.out.println("抽象类示例");
}
}
继承与抽象练习:
/*
对员工建模,员工包含3个属性:姓名,工号,工资。经理除了包含员工的属性之外,还有一个奖金属性。
*/
abstrack class Employee//员工类,父类
{
//员工的3个属性
private String name;
private String id;
private double pay;
//父类构造函数,对属性进行访问
Employee(String name,String id,double pay)
{
this.name = name;
this.id = id;
this.pay = pay;
}
public abstract void work();//定义抽象的工作方法
}
class Manager extends Employee//经理继承员工类
{
private int bonus;//经理特有属性,奖金
Manager(String name,String id,double pay,int bonus)//经理类自定义构造函数
{
super(name,id,pay);//利用super调用父类构造函数
this.bonus = bonus;
}
public void work()//经理工作方法
{
System.out.println("manager work");
}
}
class Pro extends Employee//普通员工继承员工类
{
Pro(String name,String id,String pay)//员工类自定义构造函数
{
super(name,id,pay);
}
public void work()//普通员工工作方法
{
System.out.println("pro work");
}
}
class Demo
{
public static void main(String[] args)
{
System.out.println("Demo");
}
}
//注:构造函数:给对应对象进行初始化。
抽象类相关问题:
1.抽象类中是否有构造函数?
答:有,抽象类是一个父类,要给子类提供一个实例的初始化。
2.抽象关键字abstrack不可以和哪些关键字共存?
答:fianl,被final修饰的类是不能有子类的,而被abstrack修饰的类一定是一个父类
private,抽象类中的私有的抽象方法是不能被子类所复写的。而抽象方法是子类必须复写的。
static,static修饰抽象方法,通过类名调用抽象方法是没有意义的。
3.抽象类中可不可以没有抽象方法?
答:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。
2.接口
格式:interface {}
接口中的成员修饰符是固定的:
成员常量:public static final
成员函数:public abstrack(接口中的成员都是public修饰的)
接口的出现将“多继承”通另一种形式体现出来,即“多实现”。
接口的特点:
1.接口是对外暴露的规则。
2.接口是程序的功能扩展。
3.接口可以用来多实现。
4.类与接口之间是实现关系,而且类可以 继承一个类的同时实现多个接口。
5.接口与接口之间可以有继承关系。
接口示例:
interface Inter
{
public static final int NUM = 3;
public abstract void show();
}
interface InterA
{
public abstract void show();
}
class Demo
{
public void function(){}
}
class Test extends Demo implements Inter,InterA//继承Demo,实现两个接口
{
public void show(){}
}
class InterfaceDemo
{
public static void main(String[] args)
{
Test t = new Test();
System.out.println(t.NUM);//Test实现了Inter接口
//Test实现了Inter接口,通过类名调用被static修饰的成员
System.out.println(Test.NUM);
//类名直接调用被static修饰的成员
System.out.println(Inter.NUM);
}
}
//输出结果:
3
3
3
3.多态
定义:某一类事物的多种存在形态。
例如:动物中猫,狗
猫这个对象对应的类型是猫类型:猫 x = new 猫();
同时猫也是动物中的一种,也可以把猫称为动物:动物 y = new 猫();
动物是猫和狗具体事物中抽取出来的父类型。
父类型引用指向子类对象。
体现:父类或者接口的引用指向或者接收自己的子类对象
作用:多态的存在提高了程序的扩展性和后期可维护性
前提:1.需要存在继承或者实现关系。2.要有覆盖操作。
多态的特点
成员函数:
在编译时:要查看引用变量所属的类中是否有所调用的成员。
在运行时:要查看对象所属的类中是否有所调用的成员。
成员变量:只看引用变量所属的类。
多态示例代码:
abstract class Animal//抽象类
{
abstract void eat();//动物都有吃的属性
}
class Cat extends Animal//猫继承动物类
{
//猫的特有方法
public void eat()
{
System.out.println("吃鱼");
}
public void catchMouse()
{
System.out.println("抓老鼠");
}
}
class Dog extends Animal//狗继承动物类
{
//定义狗的特有方法
public void eat()
{
System.out.println("吃骨头");
}
public void kanJia()
{
System.out.println("看家");
}
}
class Pig extends Animal//猪继承动物类
{
//定义猪的特有方法
public void eat()
{
System.out.println("饲料");
}
public void gongDi()
{
System.out.println("拱地");
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
//多态的实现
Animal a = new Cat();//类型提升。 向上转型。
a.eat();
Cat c = (Cat)a;//强制将父类的引用转成子类类型,向下转型。
c.catchMouse();
function(new Dog());
}
//定义一个方法,实现子类的特有功能
public static void function(Animal a)//Animal a = new Cat();
{
a.eat();
if(a instanceof Cat)
{
Cat c = (Cat)a;
c.catchMouse();
}
else if(a instanceof Dog)
{
Dog c = (Dog)a;
c.kanJia();
}
}
}
上述代码知识点:
转型:
Animal a = new Cat();//类型提升,向上转型。
Cat c = (Cat)a;//强制将父类的引用转成子类类型,向下转型。
instanceof : 用于判断对象的类型。 对象 intanceof 类型(类类型 接口类型)
多态中成员的特点分析:
class Fu//定义父类
{
int num = 5;
static int num2 = 4;
void method1()
{
System.out.println("fu method_1");
}
void method2()
{
System.out.println("fu method_2");
}
static void method4()
{
System.out.println("fu method_4");
}
}
class Zi extends Fu//定义子类并继承父类
{
int num = 8;
static int num2 = 9;
void method1()//覆盖父类方法
{
System.out.println("zi method_1");
}
void method3()//子类特有方法
{
System.out.println("zi method_3");
}
static void method4()
{
System.out.println("zi method_4");
}
}
class DuoTaiDemo
{
public static void main(String[] args)
{
Fu f = new Zi();//编译的时候对象没有产生,直接看左边
f.method1();//打印“zi method_1”,父类引用指向子类对象
f.method2();//打印“fu method_2”,子类继承父类方法
f.method3();//编译失败,因为父类中没有找到此方法
//--------------------------------------------------------
Fu f = new Zi();
System.out.println(f.num);//输出结果:5
//成员变量都参考引用型变量所属的类,这个地方是Fu类
Zi z = new Zi();
System.out.println(z.num);//输出结果:8
//--------------------------------------------------------
Fu f = new Zi();
f.method4();//输出结果:“fu method_4”
Zi z = new Zi();
z.method4();//输出结果:“zi method_4”
//静态方法在多态中直接参考左边,如上两类一进内存,静态直接就存在,这个时候是不用对象的
//--------------------------------------------------------
Fu f = new Zi();
System.out.println(f.num2);//输出结果:4
Zi z = new Zi();
System.out.println(z.num2);//输出结果:9
//静态的成员变量调用也是参考左边,静态其实参考的就是那个类
}
}
结论:
1.多态中成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
成员函数在多态调用时,编译看左边,运行看右边。
2.多态中成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。
3.在多态中,静态成员函数与静态变量的特点:
无论编译和运行,都参考做左边。
4.内部类
当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事务在使用外部事物的内容。
将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。
访问特点:内部类可以直接访问外部类中的成员,包括私有成员。而外部类要访问内部类中的成员必须要建立内部类的对象。
内部类定义在成员的位置上:
可以被private static成员修饰符修饰。被static修饰的内部类只能访问外部类中的静态成员。
内部类定义在局部位置上:
也可以直接访问外部类中的成员,同时可以访问所在局部中的局部变量,但必须是被final修饰的。
匿名内部类:就是内部类的简化写法。
前提:内部类要继承或实现一个外部类或者接口。
格式为:new 外部类名或者接口名(){覆盖类或者接口中的代码,()也可以自定义内容}
简单理解:就是建立一个带内容的外部类或者接口的子类匿名对象。
简单内部类示例代码:
class Outer
{
private int x = 3;
class Inner//内部类
{
//int x = 4;
void function()
{
//int x = 6;
System.out.println("innner :"+Outer.this.x);
}
}
void method()
{
Inner in = new Inner();
in.function();
}
}
class InnerClassDemo
{
public static void main(String[] args)
{
Outer out = new Outer();
out.method();
//直接访问内部类中的成员。
//Outer.Inner in = new Outer().new Inner();注意格式
//in.function();
}
}
内部类定义在局部示例:
/*
内部类定义在局部时,
1,不可以被成员修饰符修饰
2,可以直接访问外部类中的成员,因为还持有外部类中的引用。
但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。
*/
class Outer
{
int x = 3;
void method()
{
final int y = 4;//只能访问被final修饰的局部变量
class Inner
{
void function()
{
System.out.println(y);
}
}
new Inner().function();//调用方法
}
}
class InnerClassDemo
{
public static void main(String[] args)
{
Outer out = new Outer();
out.method();
}
}
匿名内部类示例:
abstract class AbsDemo//接口
{
abstract void show();
}
class Outer
{
int x = 3;
public void function()
{
new AbsDemo()//匿名内部类
{
int num = 9;
void show()
{
System.out.println("num==="+num);
}
}.show;
}
}
class InnerClassDemo
{
public static void main(String[] args)
{
new Outer().function();
}
}
5.异常
异常的体系:
Throwable
|---->Error
通常出现重大问题如:运行的类不存在或者内在溢出等,不编写针对代码对其处理
|---->Exception
在运行时运行出现的一些情况,可以通过try catch finally处理
Exception和Error的子类名都是以父类名作为后缀。
Throwable中的方法:
|---->getMessage()
获取异常信息,返回字符串。
|---->toString()
获取异常类名和异常信息,返回字符串。
|---->prinStackTrace()
获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
|---->printStackTrace(PrintStream s)
通常用该方法将异常内容保存在日志文件中,以便查阅。
throws和throw:
throws用于标识函数暴露出的异常。
throw用于抛出异常对象。
throws与throws的区别:
|---->throws用在函数上,后面跟异常类名。
|---->throw用在函数内,后面跟异常对象。
异常处理
try
{
需要被检测的代码;
}
catch
{
异常处理代码;
}
finally
{
一定会执行的代码;
}
finally代码块只有一种情况不执行,就是在之前执行了System.exit(0)。
自定义异常
自定义类继承Exception或者其子类。
通过构造函数定义异常信息。例:
class DemoException extends Exception
{
DemoException(String message)
{
super(message);
}
}
通过throw将自定义异常抛出
异常细节
RuntimeException以及其子类如果在函数中被throw抛出,可以不用在函数上声明。
一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或异常的子类。
如果父类抛出多个异常,那么重写(覆盖)方法必须抛出那些异常的一个子集,不能抛出新的异常
异常的好处:
1.将问题进行封装。
2.将正常流程代码和问题处理代码相分离,方便于阅读。
异常的处理原则:
1.处理方式有两种:try 或者 throws。
2.调用到抛出异常的功能时,抛出几个,就处理几个。一个try对应多个catch。
3.多个catch,父类的catch放到最下面。
4.catch内,需要定义针对性的处理方式。不要简单的定义printStackTrace,输出语句。也不要不写。当捕获到的异常,本功能处理不了时,可以继续在catch中抛出。
异常示例:
class Demo
{
int div(int a,int b)throws Exception//在功能上通过throws的关键字声明了该功能有可能会出现问题。
{
return a/b;
}
}
class ExceptionDemo1
{
public static void main(String[] args)
{
Demo d = new Demo();
try//try语句
{
int x = d.div(4,0);
System.out.println("x="+x);
}
catch (Exception e)//如果异常则执行catch
{
System.out.println(e.toString());//输出异常信息
}
System.out.println("over");
}
}
6.包(package)
对类文件进行分类管理。
给类提供多层命名空间。
写在程序文件的第一行。
类名的全称是:包名.类名。
包也是一种封装形式。
classpath
给jvm提供的一个环境变量。
指定类或者包所在的路径。
classpath变量值的最后有分号与无分号的区别
包之间的访问
被访问的包中的类权限必须是public的。
类中的成员权限:public或者protected
protected是为其他包中的子类提供的一种权限
package pack;
class PackageDemo
{
public static void main(String[] args)
{
packa.DemoA d = new packa.DemoA();
d.show();
}
}
package packa;
public class DemoA {
public void show()
{
System.out.println("demoa show run");
}
}
四种权限:
public | protected | default | private | |
同一类中 | √ | √ | √ | √ |
同一包中 | √ | √ | √ | |
子类 | √ | √ | ||
不同包中 | √ |
7.import,jar包,jar包的操作
import
简化类名
一个程序文件中只有一个package,可以有多个import。
用来导入包中的类,不导入包中的包。
jar包
java的压缩包
方便项目的携带
方便于使用,只要在classpath设置jar路径即可
数据库驱动,SSH框架等都是以jar包体现的
jar包的操作
通过jar.exe工具对jar的操作
创建jar包:jar -cvf mypack.jar packa packb
查看jar包:jar -tvf mypack.jar [>定向文件]
解压缩:jar -xvf mypack.jar
自定义jar包的清单文件:jar –cvfm mypack.jar mf.txt packa packb
个人总结:
本节中要理解的概念性的东西比较多,第一遍看过视频之后脑袋都是乱的,涉及到的知足点太多。这节中抽象,接口,继承,多态这几个之间的合理搭配运用是必须要掌握。重点掌握异常的获取方式和处理方式,明白自定义异常的编写方式。知识点较多,需要重复观看视频教程加深记忆与理解。面向对象中几个大块的知识点都要求必须掌握。函数的三大特征,类的各种形态,异常处理等等都是重点。