this关键字
第一部分
1.this是一个引用,this是一个变量,this变量保存了内存地址并指向自身。
2.this出现在实例方法中代表当前执行这个方法的对象。
第二部分
3.this不能使用在带有static的方法中。
第三部分
4.无法省略this的情况:
用来区分局部变量和实例变量时。
第四部分
5.通过当前构造方法调用其他构造方法
总结
static关键字
第一部分
public class Chinese {
//每一个对象的都不同
private String ID;
//每一个对象的都不同
private String name;
//每一个对象的都相同
//声明为实例对象太浪费空间
//用static关键词转化为静态变量
//静态变量在类加载的时候初始化,不需要创建对象
//用类名.静态变量名来访问
//所有static修饰的元素都是类级别特征,用类名.静态变量名来访问
static String country = "中国";
}
第二部分
public class Test {
/*1. 静态代码块
* static{
* java语句;
* }
* 2.在类加载时执行,并且只加载一次
* 3.静态代码块在一个类中可以编写多个,并遵循自上而下顺序执行
*/
static{
System.out.println("类加载");
}
public static void main(String[] args) {
System.out.println("main加载");
}
//运行结果:
//类加载
//main加载
}
第三部分
public class Testanother {
/**
* 方法什么时候定义为静态?
* (不属于某一个对象的动作了,不同的对象执行这
* 个动作结果是一样的,可以提升为类级别的动作)
*
* 静态方法中无法直接访问实例变量和实例方法
*/
int i = 100;
public void dosome(){
}
public static void main(String[] args) {
//System.out.println(i);//无法执行
Testanother t = new Testanother();
System.out.println(t.i);//可以访问
}
}
方法覆盖
回顾java语言中的方法重载:
1.方法重载又称Overload
2.方法重载什么时候使用?
-在同一个类当中,方法完成的功能是类似的
3.什么条件满足构造方法重载?
-在同一个类当中
-方法名相同
-参数列表不同(类型,顺序,个数)
4.方法重载和什么无关?
-和方法的返回值无关
-和方法的修饰符列表无关
关于java语言中的方法覆盖:
1.方法覆盖又称为方法重写,Override
2.什么时候使用方法重写?
当父类方法无法满足子类需求
子类有必要将父类继承过来的方法重新编写
这个过程被称为方法重写
3.什么条件满足后会发生方法重写?
-重写发生在具有继承关系的父子类之间
-方法重写时:方法名相同,返回值类型相同,形参列表相同
-方法重写时:访问权限只能更高不能更低
-方法重写时:抛出异常不能更多,可以更少
4.注意:
-私有方法不能继承,所以不能覆盖
-构造方法不能继承,所以不能覆盖
-静态方法不存在覆盖
-覆盖只针对方法不谈属性
//动物类
public class Animal {
//动物都可以移动
public void move(){
System.out.println("动物在移动");
}
}
//猫科类
public class Cat extends Animal{
@Override
public void move() {
System.out.println("猫在走猫步");
}
}
//飞禽类
public class Bird extends Animal{
//覆盖的是Bird当中的move方法
@Override
public void move() {
System.out.println("鸟在飞翔");
}
}
public class YingWu extends Bird {
@Override
public void move() {
System.out.println("鹦鹉飞不起起来");
}
}
public class Test {
public static void main(String[] args) {
//创建动物对象
Animal a = new Animal();
a.move();
//创建猫科类动物对象
Cat c = new Cat();
c.move();
//创建飞禽类动物对象
Bird b = new Bird();
b.move();
YingWu y = new YingWu();
y.move();
}
}
/**
* 运行结果:
* 动物在移动
* 猫在走猫步
* 鸟在飞翔
* 鹦鹉飞不起起来
*/
String常用类
字符串一旦创建不可变
//s1是一个引用指向abc
String s1 = "abc";
//可以让s1重新指向吗?
//s1是局部变量无final可以指向
//但字符串本身不可变
s1 = "def";
提高字符串访问效率(缓存技术)
//所有用“双引号”括起来的字符串都会在“字符串缓存池”中创建一份
//如果程序用到某个字串符,程序会去字符串缓存池中搜索该字符
//如果没有找到则会在其中新建该字符串,如果找到了则直接拿来用
String s1 = "abc";
String s2 = "abc";
System.out.println(s1==s2);//true
//比较两个字符是否相等,不能用 “==” 要用equals方法
System.out.println(s1.equals(s2));//true
比较
String s1 = "abc";
//只会在字符串常量池中创建“abc”对象
String s2 = new String("Hello");
//会在字符串常量池中创建“Hello”对象也会在堆中创建一个字符串对象
//第二种比较浪费内存
常用构造方法
public static void main(String[] args) {
//1.
String s1 = "abc";
//2.
String s2 = new String("abc");
//3.
byte[] bytes = {97,98,99};
String s3 = new String(bytes);
System.out.println(s3);//abc
//4.
char[] c1 = {'我','是','中','国','人'};
String s4 = new String(c1);
System.out.println(s4);//我是中国人
//5.
String s5 = new String(bytes,1,2);
System.out.println(s5);//bc
//6.
String s6 = new String(c1,2,2);
System.out.println(s6);//中国
}
常用的方法
//char charAt(int index)
//返回指定索引处的char值
String s1 = "你好世界";
char c1 = s1.charAt(2)
System.out.println(c1);//世
//boolean endsWith(String endstr)
String s1 = "你好世界";
System.out.println(s1.endsWith("你好世界"));//true
System.out.println(s1.endsWith("好世界"));//true
System.out.println(s1.endsWith("世界"));//true
System.out.println(s1.endsWith("界"));//true
System.out.println(s1.endsWith("界 "));//false
//boolean equalsIgnoreCase(String anotherString)
System.out.println("abc".equalsIgnoreCase("AbC"));//true
//int IndexOf(String str)
//第一次出现str的索引
System.out.println("http://192.168.1.100:8080/oa".indexOf("/oa"));//25
//int IndexOf(String str,int fromIndex)
System.out.println("http://192.168.1.100:8080/oa/http/oa".indexOf("/oa",27));//33
//int laseIndexOf(String str)
//最后一次出现str的索引
System.out.println("http://192.168.1.100:8080/oa/oa".lastIndexOf("/oa"));//28
//int laseIndexOf(String str,int fromIndex)
//反向搜索
System.out.println("http://192.168.1.100:8080/oa/oa".lastIndexOf("/oa",27));//25
//int length
System.out.println("http://192.168.1.100:8080/oa".length());//28
//String replaceAll (String s1,String s2)
System.out.println("你好世界你好世界".replaceAll("你好","你好 "));
//你好 世界你好 世界
//String[] split(String s)
String myTime = "2001,06,10";
String[] ymd = myTime.split(",");
for (int i = 0; i<ymd.length;i++){
System.out.println(ymd[i]);
}
//2001
//06
//10
//boolean startsWith(String s)
String s1 = "你好世界";
String s1 = "你好世界";
System.out.println(s1.startsWith("你好世界"));//true
System.out.println(s1.startsWith("你好世"));//true
System.out.println(s1.startsWith("你好"));//true
System.out.println(s1.startsWith("你"));//true
System.out.println(s1.startsWith(" 你"));//false
//转换成大写
//转换小写
//消除前后空白
System.out.println("ABCDEabcde".toUpperCase());//ABCDEABCDE
System.out.println("ABCDEabcde".toLowerCase());//abcdeabcde
System.out.println(" ABCDEabcde ".trim());//ABCDEabcde
StringBuffer 和 StringBuilder
//StringBuffer 和 StringBuilder默认初始化容量为16
//StringBuffer 和 StringBuilder底层是一个char数组,可以扩容
//优化:在创建之前,预测存储字符数量,然后在创建之时采用指定初始化容量创建
//字符串拼接建议使用 StringBuffer
public static void main(String[] args) {
//创建字符串缓冲区对象
StringBuffer sb = new StringBuffer();//16
//追加字符串
String [] ins = {"aa","bb","cc","dd"} ;
for (int i=0; i<ins.length;i++){
if(i==ins.length-1){
sb.append(ins[i]);
}else{
sb.append(ins[i]);
sb.append(",");
}
}
System.out.println(sb);//aa,bb,cc,dd
}
StringBuffer 和 StringBuilder区别
// StringBuffer是线程安全的(可以在多线程的环境下使用不会出现问题)
//StringBuilder是非线程安全的(在多线程环境下使用可能会出现问题)
一维数组
注意点
1.数组是一种引用类型
2.数组长度不可改变
静态初始化
int[] a1 = {100,200,300,400};
boolean[] b1 = {true,false,true};
String[] strs = {"a","b","c","d","e","f"};
byte[] b2 = {1,2,3};
char[] c1 = {'a','b','c'};
Object o1 = new Object();
Object o2 = new Object();
Object o3 = new Object();
Object[] obj = {o1,o2,o3};
//获取数组内元素个数
System.out.println(a1.length);
//遍历数组
for (int i = 0;i < a1.length;i++){
System.out.println(a1[i]);
}
/*执行效果
100
200
300
400
*/
System.out.println("=======================");
//修改元素
a1[1] = 100;
for (int i = 0;i < a1.length;i++){
System.out.println(a1[i]);
}
/*执行效果
100
100
300
400
*/
动态初始化
int[] z1 = new int[3];
for (int i = 0;i < z1.length;i++){
System.out.println(z1[i]);
}
System.out.println("=======================");
z1[0] = 21;
z1[1] = 22;
z1[2] = 23;
for (int i = 0;i < z1.length;i++){
System.out.println(z1[i]);
}//21 22 23
Object[] objs = new Object[3];
for (int index = 0;index < objs.length;index++){
Object o = objs[index];//null
//o.toString();//空指针异常
System.out.println(o);//null null null
}
继承
1.继承是面向对象的三大基本特征:封装,继承,多态
2.继承的基本作用:代码的复用
3.继承最重要的作用:方法覆盖,多态机制的基础
4.语法格式:
[修饰符列表] class 类名 extends 父类名{
类体 = 属性 + 方法
}
5.关于继承中的一些术语:
B类中继承A类,其中:
A类称为:父类,基类,超累,superclass
B类称为:子类,派生类,subclass
6.java语言中子类继承父类继承的都是那些数据?
-私有的不支持继承
-构造方法不支持继承
-其他数据都可以被继承
7.虽然java只支持单继承,但一个类可以间接继承其它类
8.假设一个类没有显示任何类,则默认继承java.lang.Object类
public class Account {
private String actno;
private double balance;
public Account(){
}
public Account(String actno, double balance) {
this.actno = actno;
this.balance = balance;
}
public String getActno() {
return actno;
}
public void setActno(String actno) {
this.actno = actno;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
public class CreditAccount extends Account{
private double credit;
public CreditAccount() {
}
public double getCredit() {
return credit;
}
public void setCredit(double credit) {
this.credit = credit;
}
}
public class ExtentsTest {
public static void main(String[] args) {
CreditAccount act = new CreditAccount();
act.setCredit(0.99);
act.setActno("act-001");
act.setBalance(-1000.0);
System.out.println(act.getActno() + "," + act.getCredit() + "," + act.getBalance());
}
}
多态
多态的语法
创建父类
//动物类
public class Animal {
public void move(){
System.out.println("动物在移动");
}
}
创建子类
//猫类
public class Cat extends Animal {
@Override
public void move() {
System.out.println("猫在走猫步");
}
//不是从父类中继承的方法
//子类对象特有的行为
public void catchMouse(){
System.out.println("猫捉老鼠");
}
}
//鸟类
public class Bird extends Animal {
@Override
public void move() {
System.out.println("鸟儿在飞翔");
}
public void fly(){
System.out.println("鸟儿飞");
}
}
测试
/**
*关于java语言当中的多态机制
* 1.Animal,Bird,Cat三个类的关系:
* Cat继承Animal
* Bird继承Animal
* Cat和Bird无任何继承关系
*
* 2.面向对象三大特征:封装,继承,多态
*
* 3.关于多态中涉及到的概念:
* -向上转型(upcasting)
* 子类型转化为父类型
* 又被称为:自动类型转换
*
* -向下转型(downcasting)
* 子类型转化为父类型
* 又被称为:强制类型转换【需要加强制类型转换符】
*
* -无论是向上还是向下转型,两种类型之间必须有继承关系
* 没有继承关系程序没法编译通过
*/
public class Test {
public static void main(String[] args) {
//以前编写的程序
Animal a1 = new Animal();
a1.move();
Cat c1 = new Cat();
c1.move();
c1.catchMouse();
Bird b1= new Bird();
b1.move();
//使用多态语法机制
/**
* 1.Animal与 Cat之间存在继承关系,Animal是父类,Cat是子类
*
* 2.Cat is an animal
*
* 3.new Cat()创建的的对象的类型是Cat, a2这个引用的数据类型是Animal,可见它进行了类型转换
* 子类型转换为父类型,称为向上转型/upcasting,或称为自动类型转换。
*
* 4.JAVA中允许这种语法:父类型引用指向子类型对象
*/
Animal a2 = new Cat();
/**
* 1.编译阶段 + 运行阶段
*
* 2.先分析编译阶段,再分析运行阶段,编译无法通过,根本是无法运行的。
*
* 3.编译阶段编译器检查 a2这个引用的数据类型是Animal,
* 由于Animal.class字节码当中有move()方法,所以编译通过了
* 这个过程我们称为静态绑定,编译阶段绑定,只有静态绑定成功后才有后续的运行
*
* 4.运行阶段,JVM堆内存中真实创建的对象是Cat对象,那么以下程序在运行阶段一定会
* 调用Cat对象的move()方法,此时发生的是动态绑定,运行阶段绑定。
*
* 5.无论Cat类有没有重写move方法,运行阶段一定调用的是Cat对象的move方法。
*
* 6.父类型引用指向子类型对象这种机制导致程序在编译阶段和运行阶段绑定两种不同的形态/状态,
* 这种机制可以称为动态语法机制。
*/
a2.move();//猫在走猫步
/**
* 分析以下程序为什么不能调用?
* 因为编译阶段编译器检查 a2这个引用的数据类型是Animal,
* 从Animal.class字节码文件当中查找catchMouse()方法,
* 最终没找到该方法,导致静态绑定失败,没有绑定成功,
* 也就是说编译失败,更别谈运行了
* a2.catchMouse();
*/
/**
* 需求:
* 想让 new Cat()执行catchMouse()方法,怎么办?
* 可以将a2强制转换为Cat类型
* a2的类型是Animal(父类),转换为Cat类型(子类),被称为向下转型/downcasting/强制了类型转换
*
*什么时候向下转型?
* 当调用的方法是子类型中特有的,在父类型当中不存在,必须向下转型
*/
Cat c2 = (Cat)a2;
c2.catchMouse();//猫捉老鼠
Animal a3 = new Bird();
//Cat c3 = (Cat)a3;
/**
* Exception in thread "main" java.lang.ClassCastException: Bird cannot be cast to Cat
* at Test.main(Test.java:82)
* 1.编译没有问题
*
* 2.运行阶段会出现异常,因为JVM堆内存中真实存在的对象是Bird类型,两种类型之间无继承关系,所有
* Bird对象无法转换为Cat对象
* java.lang.ClassCastException
* 类型转换异常,这种异常总是在“向下转型”时发生。
*
* 3.向下转型存在隐患(编译通过,运行出错)
* 向上转型编译通过,运行一定没问题
* 向下转型编译通过,运行可能出问题
*
* 4.如何避免java.lang.ClassCastException?
* 使用instanceof运算符可以避免以上异常。
* 4.1语法规则:
* (引用 instanceof 数据类型名)
* 4.2执行结果:true/false
* 4.3关于true/false:
* 假设:a instanceof Animal
* true:a 这个引用指向的对象是一个Animal类型
* false:a 这个引用指向的对象不是一个Animal类型
*
* 5.强制类型转换之前,建议用instanceof判断
*/
if (a3 instanceof Cat){
Cat c3 = (Cat)a3;
c3.catchMouse();
}else if (a3 instanceof Bird){
Bird b2 = (Bird)a3;
b2.fly();
}
}
}
多态的作用
测试
/**
* 以主人喂养宠物为例:
* 1.分析:主人【类】
* -喂宠物
* 宠物【类】
* -吃东西
*
* 2.多态作用:
* 降低耦合度低,提高扩展力
*
* 核心:面向抽象编程
*/
public class Test {
public static void main(String[] args) {
Master m = new Master();
m.feed(new Dog());//小狗正在啃骨头
m.feed(new Cat());//小猫正在吃鱼
m.feed(new Snake());//蛇吞象
}
}
创建宠物类
public class Pet {
public void eat(){
}
}
创建子类
public class Snake extends Pet{
@Override
public void eat() {
System.out.println("蛇吞象");
}
}
public class Cat extends Pet {
//小猫爱吃鱼
public void eat(){
System.out.println("小猫正在吃鱼");
}
}
public class Dog extends Pet {
//小狗爱吃骨头
public void eat(){
System.out.println("小狗正在啃骨头");
}
}
创建主人类
public class Master {
//主人可以喂养宠物
//主人面向的使抽象的Pet,不再面向具体的宠物
//面向抽象编程:耦合度低,扩展性强
public void feed(Pet pet){
pet.eat();
}
}
异常
1.异常是什么
第一,异常模拟的是真实世界中“不正常的事件”。
第二,java采用类去模拟异常。
第三,类是可以创建对象的。
eg.NullPointerException e = 0x1234
e是一个引用类型
e中保存的内存地址指向NullPointerException类型对象
NullPointerException是一类异常,这个对象是一个异常事件
抢劫是一个异常,而张三被抢劫就是一个异常事件
异常的作用
程序发生异常事件后,为我们提供详细的信息,使程序更加健壮
异常的继承结构
Object
Throwable (所有的异常都可抛出)
Error (没办法处理,只能退出JVM)
Exception (可处理,若不处理会退出JVM)
RunTimeException (所有RunTimeException的直接子类都是运行时异常)
编译时异常(所有Exception的直接子类)
throws关键字处理异常
在方法声明的位置使用throws关键字向上抛出异常
public static void main(String[] args){
//创建文件输入流,读取文件
FileInputStream fils = new FileInputStream("c:/ab.txt");
}
运行结果
未报告的异常错误java.io.FileNotFoundException; 必须对其进行捕获或声明以便抛出
//这是编译时异常
使用throws关键字
//public static void main(String[] args) throws IOException
public static void main(String[] args) throws FileNotFoundException {
//创建文件输入流,读取文件
FileInputStream fils = new FileInputStream("c:/ab.txt");
System.out.println("Hello World");
}
使用throws处理异常不是真正的处理异常而是推卸责任,谁调用抛给谁
运行结果
Exception in thread "main" java.io.FileNotFoundException: c:\ab.txt (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at ExceptionTest01.main(ExceptionTest01.java:8)
后续代码不执行因为JVM遇到这个异常后会退出JVM
try…catch…关键字处理异常
语法
try{
//可能出现异常的代码
}catch(//异常类型1 变量){
//处理异常的代码}
}catch(//异常类型2 变量){
//处理异常的代码}
public static void main(String[] args) {
try{
FileInputStream fils = new FileInputStream("c:/ab.txt");
fils.read();
}catch(FileNotFoundException e){
}
//编译无法通过
//未报告的异常错误java.io.IOException; 必须对其进行捕获或声明以便抛出
public static void main(String[] args) {
try{
FileInputStream fils = new FileInputStream("c:/ab.txt");
fils.read();
}catch(FileNotFoundException e){
}catch(IOException e){
}
//编译通过
catch可以写多个但必须从上到下,从小类型到大类型异常捕捉
public static void main(String[] args) {
try{
FileInputStream fils = new FileInputStream("c:/ab.txt");
fils.read();
}catch(IOException e){//大类型
}catch(FileNotFoundException e){//小类型
}
//已捕获到异常错误java.io.FileNotFoundException
try…catch只要捕捉到一个异常,处理之后就结束了
public static void main(String[] args) {
try{
FileInputStream fils = new FileInputStream("c:/ab.txt");
fils.read();
}catch(FileNotFoundException e){
System.out.println("读取文件不存在");
}catch(IOException e){
System.out.println("其他IO异常");
}
System.out.println("Hello World");
//读取文件不存在
//Hello World
finally语句快
finally语句块可以和try…catch…语句块连用
finally语句块重的代码一定会执行
public static void main(String[] args) throws FileNotFoundException {
try{
FileInputStream fils = new FileInputStream("c:/ab.txt");
//不会执行
System.out.println(("TTT"));
}finally{
//执行
System.out.println(("AAA"));
}
只要在finally语句块之前退出JVM,则finally语句块不会执行
public static void main(String[] args){
try{
//退出JVM
System.exit(0);
}finally{
//不执行
System.out.println(("AAA"));
}
一般在finally语句块中释放资源
public static void main(String[] args) {
FileInputStream fils = null;
try{
fils = new FileInputStream("c:/ab.txt");
}catch(FileNotFoundException e){
e.printStackTrace();
}finally{
if (fils!=null)
try{
fils.close();
}catch(IOException e ){
e.printStackTrace();
}
}
}
内部类
静态内部类
/**
* 关于静态内部类
* 1.静态内部类可以等同看做静态变量
*
* 内部类的作用:可以访问外部类中的私有数据
*
* 2.静态内部类可以直接访问外部类的静态数据,无法直接访问成员(变量,方法)
*/
public class demo01 {
//静态变量
static String s1 = "A";
//成员变量
private String s2 = "B";
//静态方法
private static void m1(){
System.out.println("静态的m1方法执行!");
}
//成员方法
private void m2(){
System.out.println("成员方法m2执行!");
}
//静态内部类
//可以用访问控制权限的修饰符修饰
//public,protected,private,缺省
static class InnerClass{
//定义静态方法
public static void m3(){
System.out.println(s1);
//System.out.println(s2);
m1();
//m2();
}
//成员方法
public void m4(){
System.out.println(s1);
//System.out.println(s2);
m1();
//m2();
}
}
public static void main(String[] args) {
//执行m3
demo01.InnerClass.m3();
//执行m4
InnerClass inner = new demo01.InnerClass();
inner.m4();
//运行结果:
//A
//静态的m1方法执行!
//A
//静态的m1方法执行!
}
}
成员内部类
/**
* 关于成员内部类
* 1.成员内部类可以等同看做成员变量
*
* 2.成员内部类不能有静态声明
*
* 3.成员内部类可以访问外部类所有的数据
*/
public class demo02 {
//静态变量
static String s1 = "A";
//成员变量
private String s2 = "B";
//静态方法
private static void m1(){
System.out.println("静态的m1方法执行!");
}
//成员方法
private void m2(){
System.out.println("成员方法m2执行!");
}
//成员内部类
//可以用访问控制权限的修饰符修饰
//public,protected,private,缺省
class InnerClass{
//不能定义静态方法
//成员方法
public void m4(){
System.out.println(s1);
System.out.println(s2);
m1();
m2();
}
}
public static void main(String[] args) {
demo02 demo = new demo02();
InnerClass inner = demo.new InnerClass();
inner.m4();
//运行结果:
//A
//B
//静态的m1方法执行!
//成员方法m2执行!
}
}
局部内部类
/**
* 局部内部类等同于局部变量
*
* 重点:局部内部类在访问局部变量时,局部变量要用final修饰。
*/
public class demo03 {
public void m1(){
//局部变量
final int i = 10;
//局部内部类
//局部内部类不能用访问权限修饰符修饰
class InnerClass{
//内部类不能有静态声明
//public static void m1(){}
//成员方法
public void m2(){
System.out.println(i);
}
}
//调用m2
InnerClass inner = new InnerClass();
inner.m2();
}
public static void main(String[] args) {
demo03 oc = new demo03();
oc.m1();
//运行结果:
//10
}
}
匿名内部类
/**
* 匿名内部类:指的是类没有名字
*
* 优点:少用一个类
* 缺点:无法重复使用
*/
public class demo04 {
//静态方法
public static void test(CustomerService cs){
cs.logout();
}
public static void main(String[] args) {
//调用test方法
/**
* demo04.test(new CustomerServiceimp());
* 运行结果:
* 系统已安全退出
*/
//使用匿名内部类执行test方法
//new CustomerService(){}就是匿名内部类
test(new CustomerService() {
@Override
public void logout() {
System.out.println("系统已安全退出");
}
});
//运行结果:
// 系统已安全退出
}
}
//接口:
interface CustomerService{
//退出系统
void logout();
}
//编写一个类实现CustomerService接口
/**
* class CustomerServiceimp implements CustomerService{
*
* @Override
* public void logout() {
* System.out.println("系统已安全退出");
* }
* }
*/
抽象类
抽象类语法
1.如何定义抽象类:
class关键字前加 abstract
2.抽象类无法被实例化
3.抽象类也有构造方法,该构造方法给子类创建对象用的
4.抽象方法的语法:在方法的修饰符列表中添加 abstract 关键字,并且以“;”结束,不带有“{}”
5.抽象类中不一定有抽象方法,但抽象方法必须出现在抽象类中
6.一个非抽象类继承抽象类,必须把抽象类中的抽象方法覆盖,实现,重写。
/**
* 1.如何定义抽象类:
* class关键字前加 abstract
* 2.抽象类无法被实例化
* 3.抽象类也有构造方法,该构造方法给子类创建对象用的
* 4.抽象方法的语法:在方法的修饰符列表中添加 abstract 关键字,并且以“;”结束,不带有“{}”
* 5.抽象类中不一定有抽象方法,但抽象方法必须出现在抽象类中
* 6.一个非抽象类继承抽象类,必须把抽象类中的抽象方法覆盖,实现,重写。
*/
public abstract class Abstract {
Abstract(){
System.out.println("A.....");
}
//抽象方法
public abstract void m1();
//入口
public static void main(String[] args) {
//抽象类无法创建对象
//Abstract a = new Abstract();
//多态
Abstract a = new B();
a.m1();
}
}
class B extends Abstract{
public void m1(){
System.out.println("m1方法执行");
}
B(){
super();//父类构造方法虽然调用了,但并没有创建父类对象
System.out.println("B.....");
}
}
接口的基本语法
1.如何定义接口:
[修饰符] interface 接口名()
2.接口中只能出现:常量,抽象方法
3.接口是一个特殊的抽象类,接口是完全抽象的。
4.接口中无构造方法,接口无法被实例化。
5.接口和接口之间可以多继承
6.一个类可以实现多个接口(等同于继承)
7.一个非抽象的类实现接口,需要将接口中的所有方法(实现/覆盖/重写)
public class Interface {
public interface A{
//常量(必须用final修饰)
public static final String SUCCESS = "success";
public static final double PI = 3.14;
//public static final可以省略
byte MAX_VALUE = 127;
//抽象方法(接口中所有的抽象方法都是public abstract)
public abstract void method1();
//public abstract可以省略
void method2();
}
//多继承
interface B{
void method1();
}
interface C{
void method2();
}
interface D{
void method3();
}
interface E extends B,C,D{
void method4();
}
//implements是实现的意思,是一个关键字
//implements和extents意义相同
//MyClass不是抽象类
class MyClass implements B,C{
@Override
public void method1() { }
@Override
public void method2() { }
}
//E继承B,C,D默认其中有method1,2,3外加其本身method4
class F implements E{
@Override
public void method1() { }
@Override
public void method2() { }
@Override
public void method3() { }
@Override
public void method4() { }
}
}
接口
接口的作用
1.使项目分层,所有层都面向接口开发,开发效率提高
2.接口使代码和代码之间耦合度降低,可以随意切换
接口代码
/**
* 客户业务接口
*/
public interface CustomerService {
//定义一个退出系统的方法
void logout();
}
面向接口实现类
/**
* 编写接口的实现类
*/
public class CustomerServiceImp implements CustomerService{
public void logout(){
//对接口中的抽象方法进行实现
System.out.println("成功退出系统");
}
}
main方法
public class Test {
//入口
public static void main(String[] args) {
//执行logout()方法
//以下程序面向接口调用
//编译看左边,运行看右边
CustomerService cs = new CustomerServiceImp();//多态
//调用
cs.logout();
}
}
举例
/**
* 汽车和发动机之间的接口
* 生产汽车的厂家面对接口生产
* 生产发动机的厂家面对接口生产
*/
public interface Engine {
//所有发动机都可以启动
void start();
}
public class YAMAHA implements Engine {
public void start (){
System.out.println("YAMAHA启动");
}
}
public class HONDA implements Engine{
public void start (){
System.out.println("HONDA启动");
}
}
//生产汽车
public class Car {
//引擎
//面向接口编程
Engine e;
//Constructor
Car(Engine e){
this.e = e;
}
//测试引擎
public void testEngine(){
e.start();
}
}
public class TestCar {
public static void main(String[] args) {
//生产引擎
YAMAHA e1 = new YAMAHA();
//生产汽车
Car c = new Car(e1);
//测试引擎
c.testEngine();
//换HONDA
c.e = new HONDA();
}
}
总结
接口和抽象类都能完成某个功能,优先选择接口
因为接口可以多实现,多继承
并且一个类除了实现接口之外还呢个去继承其他类