B站黑马教程,边看边记。略粗糙,建议视频加笔记
文章目录
数据类型
基本类型
- int 整型
- boolean 布尔型
- short 短整型
- long 长整型
- char 字符型
- byte 字节型
- float 单精度浮点型
- double 双精度浮点型
引用类型
- String 字符串
- 数组
- 类
- 接口等等
数据转换
自动类型转换(隐式)
规则:数据范围从小到大,跟字节无关
例
long num1 = 100 (long数据范围 > int)//100
double num2 = 100F (double > float)//2.5
float num3 = 30L (float > long 虽然long内存占比大于float 但是数据范围float大于long)//30.0
强制类型转换
格式 int num1 = (int) 100L
不推荐使用,会发生数据的溢出或损失
例:
int num2 = (int) 6000000000L //1705032704溢出
int num3 = (int)3.5 //3精度损失
扫描二维码关注公众号,回复: 12672963 查看本文章![]()
byte/char/short 三种类型都可以发生数学运算
会被先提升为int型,然后进行计算
例:
char str1 = 'A';
System.out.println(str1 + 1); //66 'A'会被先提升为int,值为65,再进行计算。其他同理
根据变量优化,重要的一点是,如果提升以后,要用int接收
例:
short a = 8;
short b = 5;
short res = a+b;//报错,因为此时a、b会被提升为int,需要用int去接收
int res = a+b;
Java当中的内存划分
栈(Stack)
存放的都是方法中的局部变量,有作用域,出域出栈。方法的运行一定要在栈当中。
堆(Heap)
存放的都是new出来的东西,例如数组
,堆内存里的东西都有一个地址值,16进制。
- 整数 默认值:0
- 浮点数 0.0
- 字符 ‘u\000’
- 布尔 false
方法区(Method Area)
存储.class相关信息,包含方法的信息
本地方法栈(Native Method Stack)
与操作系统相关
寄存器(pc Register)
与CPU相关,性能特别高
面向对象思想是一种更符合我们思考习惯的思想,它可以将复杂的事情简单化,并将我们从执行者变成了指挥者。
面向对象的语言中,包含了三大基本特征,即封装
,继承
,多态
类和对象
类:一组相关属性和行为的集合
对象:是一类事物的体现,对象是类的实例,对象是实体,类是抽象的
重写和重载
重写(@Override):再继承关系当中,方法的名称一样,参数列表也一样。
重载(Overload):方法的名称一样,参数的列表不一样
public class Fu{
public viod method(){
}
}
public class Zi extends Fu{
@Override
public void method(){
}
}
子类方法的返回值必须小于等于父类方法的返回值范围。
public class Fu{
public viod method(){
return null
}
}
public class Zi extends Fu{
public String method(){
return null
}
}
// String 比父类小
子类方法的权限必须大于等于父类方法的权限修饰符
public
> protected
> (default)
> private
example:
public class Phone{
public void call(){
}
public void send(){
}
public void show(){
System.out.println("show numbers");
}
}
public NewPhone extends Phone{
public void show(){
// 尽量不要动父方法
super.show();
System.out.println("show ava");
System.out.println("show name");
}
}
构造方法
子类构造方法当中有一个默认隐含的super()
调用,所以一定是先调用的父类构造,后执行子类
子类构造可以通过super
调用父类重载构造
public class Fu {
public Fu() {
}
public Fu(int num) {
}
}
public Zi extends Fu{
public Zi(){
//super(); 只能调用一次 不能两个都调用
super(num : 20);
}
}
抽象类
抽象方法,就是加上abstract关键字,然后去掉大括号,直接分号结束
public abstract class Animal{
// 这是一个抽象方法
public abstract void eat();
}
抽象类不一定必须有抽象方法
抽象类不能直接创建一个实例,而是用一个子类去继承抽象父类
子类必须覆盖重写抽象定义的所有方法,覆盖重写(实现),子类去掉抽象方法的abstract关键字,然后补上括号并实现
public class Cat extends Animal{
@Override
public void eat(){
System.out.println("eat fish");
}
}
创建子类进行使用
Cat catOne = new Cat();
carOne.eat();
抽象类可以有构造方法,是供子类创建对象的时候,初始化父类成员使用的
public abstract class Fu{
public Fu(){
System.out.println("fu constractor")
}
public abstract void eat();
}
public class Zi extends Fu{
public Zi(){
System.out.println("Zi constractor")
}
@Override
public void eat(){
System.out.println("eat fish");
}
}
public class Example {
public static void main(String[] args){
Zi zi = new Zi();
zi.eat();
//"fu constractor"
//"Zi constractor"
//"eat fish"
}
}
如果子类不覆盖重写抽象父类的抽象方法,那么子类也必须是一个抽象类
public abstract class Animal{
public Animal(){
System.out.println("Animal constractor")
}
public abstract void eat();
public abstract void sleep();
}
public abstract class Dog extends Animal{
// 不加abstract报错,下面没有重写sleep抽象方法,这也是个抽象类,需要孙子类去实现重写
public Dog(){
System.out.println("Dog constractor")
}
@Override
public void eat(){
System.out.println("eat meat");
}
}
public class DogA extends Dog(){
@Override
public void sleep(){
System.out.println("hehehehe~");
}
}
public class DogB extends Dog(){
@Override
public void sleep(){
System.out.println("huhuhuhu~");
}
}
接口
接口就是多个类的公共规范
接口是一种引用数据类型
,最重要的内容就是其中的抽象方法
定义
public interface 接口名称{
// 接口内容
}
换成了关键字interface
之后,编译生成的字节码文件仍然是.java
->.class
如果是java7 还可以额外包含的内容有:常量
抽象方法
如果是java9 还可以额外包含私有方法
public interface MyInterfaceAbstract{
// abstract method
public abstract void method();
// public abstract 可省略
}
使用(实现)
public class 实现类名 implements 接口名称{
// ...
// 必须覆盖重写接口(实现)中所有的抽象方法,类似抽象类的抽象方法
}
example:
public interface MyInterfaceAbstract{
public abstract void method();
// default method 默认方法会被实现类继承
public default void methodDefault(){
// 接口的默认方法,可以通过接口实现类对象,直接调用
// 接口的默认方法,也可以被解耦实现类进行覆盖重写
System.out.println("interface default method");
}
}
public class MyInterfaceAbstractImplA implements MyInterfaceAbstract{
@Override
public void method(){
System.out.println("override interface");
}
}
public class MyInterfaceAbstractImplB implements MyInterfaceAbstract{
@Override
public void method(){
System.out.println("override interface");
}
@Override
public default void methodDefault(){
System.out.println("override interface default method");
}
}
public class InterfaceTest {
public static void main(String[] args){
MyInterfaceAbstractImplA a = new MyInterfaceAbstractImplA();
a.method(); //调用的实现类的方法
//调用默认方法,如果实现类当时中没有,会向上找接口
a.methodDefault(); // interface default method
MyInterfaceAbstractImplB b = new MyInterfaceAbstractImplB();
b.method();
b.methodDefault(); //override interface default method
}
}
接口里定义静态方法
就是将abstract
或者default
换成static
即可,带上方法体
public static 返回值类型 方法名称(参数列表){
//方法体
}
public interface MyInterfaceStatic{
public static void methodStatic(){
System.out.println("this is a static interface method");
}
}
// Error use ******
public class InterfaceA implements MyInterfaceStatic{
}
public class Test{
public static void main(String[] args){
InterfaceA a = new InterfaceA();
a.methodStatic();
}
}
// Correct use ******
public class Test{
public static void main(String[] args){
MyInterfaceStatic.methodStatic();
}
}
Question:
我们需要抽取一个共有方法,用来解决两个默认方法之间重复代码的问题,但是这个共有方法不应该让实现类使用,应该是私有化的。
解决方案
从java9开始,接口当中允许定义私有方法。
普通私有方法,解决多个默认方法之间重复代码的问题
private 返回值类型 方法名称(参数列表){
// 方法体
}
静态私有方法,解决多个静态方法之间重复代码的问题
private static 返回值类型 方法名称(参数列表){
// 方法体
}
example:
public interface MyInterfacePrivateA{
public default void methodDefault01(){
System.out.println("default method A");
methodCommon();
}
public default void methodDefault02(){
System.out.println("default method B");
methodCommon();
}
private void methodCommon(){
System.out.println("default method AAA");
System.out.println("default method BBB");
}
}
public class MyInterfaceAAA implement MyInterfacePrivateA{
public void methodAnother(){
// methodCommon(); error 访问不到
}
}
//静态方法同默认方法
Interface 中的成员变量(也就是常量)
必须使用public static final三个关键字进行修饰
public interface MyInterface{
// 这其实就是一个常量,一旦赋值,不可以修改,接口中名称使用完全大写用下划线分割
public static final int NUM = 10;
// public static final 可以省略
}
Java 9+版本中,接口的内容可以有:
- 成员变量其实就是常量,格式[public] [static] [final] 数据类型 = 数据值
- 接口中最重要的就是抽象方法,格式 [public] [abstract] 返回值类型 方法名称(参数列表)
- 从Java8开始,接口里允许定义默认方法,格式:[public] default 返回值类型 方法名称(参数列表)
- 从Java8开始,接口里允许定义静态方法,格式[public] static 返回值类型 方法名称(参数列表)
- 从Java9开始,接口里允许定义私有方法,格式:普通私有方法:private 返回值类型 方法名称(参数列表) 静态私有方法 private static 返回值类型 方法名称(参数列表)
一个类的直接父类是唯一的,但是一个类可以同时实现多个接口
public class MyInterfacceImpl implements InterfaceA, InterfaceB{
// 覆盖重写所有抽象方法
@Override
public void methodA(){
// 实现接口A中的抽象方法
}
@Override
public void methodB(){
// 实现接口B中的抽象方法
}
// 如果两个接口中有相同的抽象方法,只需覆盖重写一次即可
@Override
public void method(){
// 实现共有抽象方法
}
// 如果A跟B中有冲突的默认方法,实现类里面也得覆盖重写
@Override
public void methodDefault(){
// 实现冲突默认方法
}
}
多态
面向对象的三大特征:封装性,继承性,多态性。
extends继承或者implements实现,是多态性的前提
代码当中体现多态性,其实就是一句话,父类引用指向子类对象
格式
/**父类名称 对象名 = new 子类名称();
*或者
*接口名称 对象名 = new 实现类名称();
*/
public class Fu{
public void method(){
System.out.println("i'm a father method");
}
public void fuMethod(){
System.out.println("i'm a father personal method");
}
}
public class Zi extends Fu{
@Override
public void method(){
System.out.println("i'm a son method");
}
}
// 多态的写法
public class Test{
public static void main(String[] args){
// 左侧父类的引用,指向了右侧子类的对象
Fu obj = new Zi();
obj.method(); // i'm a son method
obj.fuMethod(); // i'm a father personal method
}
}
总结:左父右子就是多态,一只猫被当作动物来看待,也是正确的。这就是多态的特征。
访问成员变量的两种方式:
- 直接通过对象名称访问成员变量,看等号左边是谁,优先用谁,没有则向上找。
- 简介通过成员变量访问
public class Fu{
int num = 10;
public void method(){
System.out.println("i'm a father method");
}
public void fuMethod(){
System.out.println("i'm a father personal method");
}
}
public class Zi extends Fu{
int num = 20;
int zinum = 30;
@Override
public void method(){
System.out.println("i'm a son method");
}
}
// 成员变量不能进行覆盖重写
public class Test{
public static void main(String[] args){
// 左侧父类的引用,指向了右侧子类的对象
Fu obj = new Zi();
System.out.println(obj.num) // 10
System.out.println(obj.zinum) // error 只能向上查找,不能向下查找,左边为父
}
}
用途举例:
抽象类或接口:Employee 员工
抽象方法: work(); 工作
Employee |
---|
work() |
有教师和助教两个角色继承Employee或实现Employee接口
Teacher | Assistant |
---|---|
work()(讲课) | work()(辅导) |
如果不使用多态
Teacher one = new Teacher();
one.work();//讲课
Assistant two = new Assistant();
two.work();//辅导
但是现在唯一要做的事就是调用work()
方法,其他的功能不关心
如果使用多态
Employee one = new Teacher();
one.work();//讲课
Employee two = new Assistant();
two.work();//辅导
这样的好处是,无论右边new的时候换成哪个子类对象,等号左边调用的方法不会变化。让我们的代码更灵活
对象的向上转型,其实就是多态的写法
注意事项:向上转型一定是安全的,因为是从小范围转向了大范围。
但是一旦向上转型以后,就无法调用子类的方法!
为了避免无法调用子类的方法而向下转型:
子类名称 对象名 = (子类名称)父类对象
example:
Teacher one = (Teacher) Employee;
// 将父类对象还原成原来的子类对象,但是必须之前是什么子类就得转换成什么子类。
如何才能知道一个父类引用的对象,本来是什么子类。
格式:
对象 instanceof 类名称
//这样对得到一个boolean值结果,也就是判断前面的对象能不能当时做后面类型的实例。
example:
public class Test{
public static void main(String[] args){
// 。。。
}
public void giveAnimal(Animal animal){
// 如果不知道animal的类型
if (animal instanceof Dog){
Dog dog = (Dog) animal;
dog.watchHouse();
} else{
Cat cat = (Cat) animal;
cat.eatFish();
}
}
}