没有代码块并且使用abstract修饰的方法。
抽象方法必须在抽象类中。
该类里的某个方法不太好实现并且该方法又应该在该类里,就不写代码块,将该方法变为抽象方法,抽象方法交给非抽象的子类去实现。
abstract修饰符.
public abstract class Person {
//抽象方法:交给非抽象的子类去实现
public abstract void eat();
}
//在非抽象的子类方法中去实现方法
public class Japanese extends Person {
@Override
public void eat() {
System.out.println(super.getName() + "吃米饭");
}
}
使用abstract修饰的类.
1.可以使用new关键字来创建抽象类对象吗?
答:不可以。
补充:匿名内部类的步骤:
(1).顶层建立一个匿名类(没有名字的类);
(2).继承A类,实现A类的抽象方法;
(3).创建匿名对象。
很多人容易把匿名内部类当成使用new关键字创建抽象类的对象,这里一定要注意。
2.抽象类中只有抽象方法吗?
答:抽象类中就可以有静态方法和成员方法。
3.抽象类中可不可以没有抽象方法?
答:可以,但毫无意义。
4.如果父类是抽象类,则子类必须实现父类的抽象方法吗?
答:不是,子类如果是抽象类,可以不去实现父类的抽象方法。
5.抽象类能不能有构造方法?作用是什么?
答:可以。作用是让子类调用,给父类的属性赋值。
接口是特殊的抽象类。
implements是实现接口的关键字;
interface是定义接口的关键字。
在JDK1.8之前,接口里只有静态常量和抽象方法;JDK1.8开始,接口里就有了默认方法和静态方法。
抽象类中只有静态常量或者静态方法就用接口替代。
接口更像一个规范/标准
1.一个类可以实现多个接口吗?
答:可以。
2.一个接口可以实现多个接口吗?
答:不可以。
3.接口里边的方法一定都是抽象的吗?
答:不一定。JDK1.8之后就允许使用静态方法和默认方法。
4.接口解决了单线程的问题。
5.一个类是否可以继承一个类,并同时实现多个接口?
答:可以。
6.接口可以new对象吗?
答:不可以。new出来的是匿名内部的对象
7.多个接口中有相同的抽象方法,在实现类中实现几个方法?
答:只有一个。
//I1和I2的默认方法名冲突了,在A类中就必须重写
@Override
public void method02() {
//可以在实现类中调用指定接口的默认方法
I1.super.method02();
System.out.println("xxxx");
}
子类对象指向父类引用(父类引用里存的是子类对象在堆里开辟的地址)。
Vehicle v = new Bike();
//Vehicle是父类,Bike是子类
实现类的对象指向接口的引用(接口的引用中存的是实现类对象在堆内存里开辟的地址)。
IUSB usb = new Disk();
//IUSB是接口,Disk是实现类
O - open - 在需求更改时,对创建类是欢迎的
C - close - 在需求更改时,改变原有类是拒绝的
P - principle(原则)
父子类关系
向上转型:子类类型 转 父类类型
(1)向上转型就是多态;
(2)可以调用父类非私有化属性;
(3)可以调用父类非私有化方法;
(4)可以调用子类重写父类的方法;
(5)不可以调用子类属性;
(6)不可以调用子类方法。
优点:在需求更改时符合OCP原则
缺点:不可以调用子类/实现类自己独有的属性和方法
向下转型:父类类型 转 子类类型 (强转)
向下转型不安全,容易出现ClassCastException(类型转换异常),所以不能直接将父类对象强转为子类类型。
解决方案:向下转型一定要向上转型后再向下转型;
向下转型一定要用instanceof判断。
Animal an = new Cat();//向上转型
//Animal an = new Dog();//向上转型
if(an instanceof Dog){
//判断引用an所执行的对象是否是Dog类型的
Dog dog = (Dog) an;//向下转型
System.out.println(dog);
}else if(an instanceof Cat){
//判断引用an所执行的对象是否是Cat类型的
Cat cat = (Cat) an;
System.out.println(cat);
}
在一个类的内部定义的类称为内部类。内部类允许把一些逻辑相关的类组织在一起,并且控制内部类的可视性。
成员内部类里可以调用外部类的所有属性
静态内部类只能调用外部类的静态属性
接口内部类可以调用外部接口的静态常量
局部内部类可以调用外部类当前方法的局部变量 + 所有属性
注意:(1)不能用访问修饰符修饰局部变量
(2)在局部内部类中调用方法中的局部变量,在JDK1.8版本之前,该变量必须手动添加final;在JDK1.8版本之后,该变量会自动转换为常量。
(3)不能用访问修饰符修饰局部内部类
面试题:为什么局部内部类中调用方法中的局部变量,该变量会变成常量?
答:变成常量后,该量存放在常量池中,比局部变量的生命周期更长,保证内部类对象可以随时调用该常量。
应用场景1:如果抽象类的子类只使用一次,就直接用匿名内部类代替,减少了子类的创建
应用场景2:如果接口的实现类只使用一次,就直接用匿名内部类代替,减少了实现类的创建
/** 1.创建匿名类
* 2.匿名类继承A类,重写A类的抽象方法
* 3.创建匿名类的对象
* 4.该对象指向父类的引用(多态)
*/
A a = new A() {
@Override
public void method() {
System.out.println("xxx");
}
};
a.method();
/**
* 1.创建匿名类
* 2.匿名类实现I1接口,重写I1的抽象方法
* 3.创建匿名类的对象
* 4.该对象指向接口的引用(多态)
*/
I1 i1 = new I1() {
@Override
public void method() {
System.out.println("xxxxxxxxxxx");
}
};
i1.method();
8种基本数据类型对应的8个类
Java为纯面对对象语言(万物皆对象),8种基本数据类型不能创建对象,破坏了Java为纯面对对象语言的特征,Java就给8种基本数据类型分别分配了对应的类,这种类就叫做包装类(封装类)。
基本数据类型 | 包装类 | 继承关系 |
---|---|---|
byte | Byte | extends Number extends Object |
short | Short | extends Number extends Object |
int | Integer | extends Number extends Object |
long | Long | extends Number extends Object |
float | Float | extends Number extends Object |
double | Double | extends Number extends Object |
char | Character | extends Object |
boolean | Boolean | extends Object |
注释:int的包装类是Integer,char的包装类是Character,其余基本数据类型的包装类都是首字母大写。
集合。集合是存放数据的容器,和数组类似,但集合只能存引用数据类型的数据,要想集合存储基本数据类型,就可以将基本数据类型装箱成对应的引用数据类型。
基本数据类型 --> 包装类的对象
关键字:valueOf、Integer
int i = 10;
Integer integer = Integer.valueOf(i);
System.out.println(integer);
包装类的对象 --> 基本数据类型
关键字:intValue/…Value
Integer integer = new Integer();
int i = integer.intValue();
System.out.println(i);
从JDK1.5开始,就可以自动装箱和自动拆箱了。
int i = 10;
Integer integer = i;//底层实现与手动装箱一样
System.out.println(integer);
Integer integer = new Integer();
int i = integer;
System.out.println(i);
1.将String类型数组转换为int类型的数组。
//将String[] s = {"1","2","3","4","5","6"}转换为int类型的数组
String[] s = {
"1","2","3","4","5","6"};
int[] x = new int[s.length];
for(int i = 0;i < x.length;i++){
Integer integer = Integer.valueOf(s[i]);
is[i] = integer;//自动拆箱
}
for(int e : x){
System.out.println(e);
}
2.判断下列代码为true还是false
Integer integer1 = Integer.valueOf(100);
Integer integer2 = Integer.valueOf(100);
System.out.println(integer1 == integer2);//true
Integer integer3 = Integer.valueOf(200)