Java 基础笔记

JRE与JDK

JRE(Java Runtime Environment Java运行环境):
包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。
JDK(Java Development Kit Java开发工具包):
JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE,所以安装了JDK,就不用在单独安装JRE7。
其中的开发工具:编译工具(javac.exe)打包工具(jar.exe)等

简单而言:使用JDK开发完成的java程序,交给JRE去运行。

原码、补码、反码

在这里插入图片描述
数字以原码的形式存在、计算时以补码进行计算

变量相加、常量相加

在这里插入图片描述
Java有常量优化机制,编译时直接将常量相加的结果当成一个数。

A:在定义Long或者Float类型变量的时候,要加L或者f.

  • 整数默认是int类型,浮点数默认是double. byte,short在定义的时候,他们接收的其实是一个int型的值.
  • 这个是自己做了一个数据检测的,如果不再它们的范围内,就报错.

B:byte值的问题

  • byte b1=127;byte b2=(byte)300;byte b4=(byte)130;
  • byte的范围:-128 ~ 127

C:数据类型转换之默认转换

  • byte,short,char–int–long–float–double long:8个字节float:4个字节
  • IEEE754
  • 4个字节是32个二进制位
  • 1位是符号位8位是指数位
  • 23位是尾数位
  • 每个指数位减去121
  • A:它们底层的存储结构不同。
  • B:float表示的数据范围比long的范围要大

D:Java语言中的字符char可以存储一个中文汉字吗?为什么呢?

可以,因为Java语言采用的是Unicode编码.Unicode编码中的每个字符占用两个字节.
所以,Java中的字符可以存储一个中文汉字

逻辑运算符

&& 与 || 是具有短路性质,当按优先级顺序计算到当前表达式时,表达式的结果可以确定整个表达式的结果时,便不会继续向后进行判断和计算,而直接返回结果。

例如:当使用 && 逻辑运算符时,在两个操作数都为 true 时,结果才为 true,但是当得到第一个操作为 false 时,其结果就必定是 false,这时候就不会再判断第二个操作了。在计算表达式 (a & b) && (a | b) 时,首先计算 a & b 得到了 false,因为之后是 &&,任何值与 false 进行与操作都是 false,所以可以不用再计算下去,而直接返回 a & b 的结果 false。

键盘输入输出

import java.util.scanner;

scanner sc = new scanner(System.in);

int x = sc.nextInt();//输入

System.out.println("输出:"+x);

运算符

  • 1^:相同为0,不同为1,一个数据对另一个数据位异或两次,该数本身不变。

  • 2<<:左移 左边最高位丢弃,右边补齐

  • 3>>:右移 最高位是0,左边补齐0;最高位是1,左边补齐1

  • 4 >>>:无符号右移无论最高位是0还是1,左边补齐0

转移字符

‘\t’:tab键的位置,制表符
‘\r’:回车
‘\n’:换行

Java内存分配

Java程序在运行时,需要在内存中的分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。

  • 栈存储局部变量(在方法中和方法上定义)
  • 堆存储new出来的东西
  • 方法区(面向对象部分讲)
  • 本地方法区(和系统相关)
  • 寄存器(给CPU使用)

栈也叫内存,是Java程序的运行区,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束,该栈就over。
栈中的数据都是以栈帧(stack Frame)的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关 方法(Method)和运行期数据的数据集,当一个方法A被调用时就产生了一个栈帧F1,并被压入到栈中,A方法又调用了B方法,于是产生栈2也被压入,执行完毕后,先弹出F2栈帧,再弹出F1栈帧,遵循"先进后出"原则。

那帧中到底存在着什么数据呢?栈帧中主要保存3种数据:

  • 本地变量(Local Variables),包括输入参数和输出参类似及方法内的变量;
  • 栈操作(operand stack),记录出栈、入栈的操作;
  • 栈帧数据(Frame Data),包括类文件、方法等等。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

垃圾回收机制

栈中变量使用完毕就出栈,线程结束该栈也就释放。

堆中对象:当没有任何引用指向堆内存的对象的时候,该对象变成垃圾。jvm的垃圾回收机制,会在不定时对其进行回收。

Java中到底是传值还是传址?

  1. Java中即传值也传址,基本数据类型传的是值,引用数据类型传的是址(地址)
  2. Java中是传值,非传址,因为地址值也是值(高司令支持)
    在这里插入图片描述

change()中对传入的arr数组进行操作,因为传入的数据是引用数据类型(指针、数组),是堆中的地址,所以操作以后数据改变了。

如果传入的是基本数据类型(int等),这时change()中操作的值是栈中保存在change方法内的变量,运行完以后栈中change()释放,所以保存在栈的main()中数据没有改变。

对象的内存

方法用完就出栈。new出来的东西(实例)存在堆中。方法区存的是每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。

在这里插入图片描述

匿名对象易产生垃圾

在这里插入图片描述

static

在类中变量定义为static后,这个变量就变成对象之间共有的了,保存在方法区中,其他的非静态成员变量保存在堆中各自的对象中。

非静态的成员方法可以访问静态的成员,静态方法不能访问非静态的成员。(因为静态成员是优先于对象存在的,是随着类加载而加载的,所以他不能知道后续创建的对象中有什么)

静态的成员方法也没有this关键字,因为this是随着对象的创建而存在的。

所以成员方法中加了static以后,可以“xx类.xx方法”直接调用,如果没有加static,就必须先创建(new)一个该类对象x,然后"对象x.xx方法"调用。

静态变量可以通过类名调用,也可以通过对象调用;成员变量只能通过对象名调用

public static void main(String[]args)()

public被jvm调用,访问权限足够大

static被jvm调用,不用创建对象,直接类名访问

void被jvm调用,不需要给jvm返回值

main一个通用的名称,虽然不是关键字,但是被jvm识别

string[]args以前用于接收键盘录入的

Java中类的继承的特点

Java不支持多继承,但是支持多层继承

在这里插入图片描述
子类只能继承父类的非私有成员,子类不能继承父类的构造函数,但是能通过super语句访问父类构造方法。

什么时候使用继承?如果有两个类A,B.只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。

不要为了部分功能去使用继承。

继承中父类子类中同名成员变量的关系:就近原则,自己有就不用父类的,super可以调用父类的成员变量。
在这里插入图片描述

方法重写override、重载overload

父类中私有方法不能被重写,因为父类私有方法子类根本就无法继承。

子类重写父类方法时,访问权限不能更低,最好就一致

父类静态方法,子类也必须通过静态方法进行重写,其实这个算不上方法重写,但是现象确实如此。

overload可以改变返回类型,overload方法名相同,参数列表不同。

override方法名参数列表与父类方法的都相同。

子类调用重写方法:创建子类对象,先从子类找方法,如果没有就找父类的。

final

final修饰类,类不能被继承。

final修饰方法,不能被重写。

final修饰变量,被称为常量,不能被修改。
在这里插入图片描述
final修饰引用数据类型,地址不能改变,但是地址指向的值可以改变。
在这里插入图片描述
final修饰成员变量必须要初始化,可以在定义时直接赋值,也可以在构造函数中赋值。

多态

三个前提:
继承、重写、父类引用指向子类对象。

Animal父类,Cat子类,调用非静态的重写方法时,编译时看的是父类的方法,执行时看的是子类的方法(动态绑定)。

因为静态方法是属于类的,所以静态方法不存在覆盖一说。调用静态的重写方法时,编译时看的是父类的方法,运行时也是父类的方法。

成员方法:编译看父类,执行看父类。

向上转型:父类引用指向子类对象(自动类型提升)
在这里插入图片描述
弊端:不能使用子类特有功能。

在这里插入图片描述

抽象类

抽象类和抽象方法必须用abstract关键字修饰:

abstract class 类名{ }
public abstract void eat();

抽象类不一定有抽象方法,有抽象方法的类一定是抽象类

抽象类不能实例化(创建对象)那么,抽象类如何实例化呢?通过继承抽象类。按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。

抽象类的子类:要么是抽象类、要么重写抽象类中的所有抽象方法

一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
可以,这么做目的只有一个,就是不让其他类创建本类对象,交给子类完成

abstract不能和private共存,因为private不能被子类继承,abstract必须重写方法,矛盾。

abstract不能和static共存,因为static可以通过类名直接调用,abstract必须先重写方法。

abstract不能和final共存,因为final不能被重写,abstract必须重写。

接口

从狭义的角度讲就是指java中的interface,从广义的角度讲对外提供规则的都是接口。

接口不能实例化,通过继承来实现。

接口中所有的方法都是public abstract抽象的(不能有方法体),接口中所有的成员变量都是public static final 的(常量)。

重写接口的方法必须是public。

接口的子类可以是抽象类,也可以是具体类(要实现接口中所有的方法)。
在这里插入图片描述
接口与接口之间是继承关系,可以多继承。

在 Java8 中:
接口不能用于实例化对象。
接口中方法只能是抽象方法、default 方法、静态方法。
接口成员是 static final 类型。
接口支持多继承。

在 Java9 中,接口可以拥有私有方法和私有静态方法,但是只能被该接口中的 default 方法和静态方法使用。
多态的好处:提高了代码的维护性(继承保证),提高了代码的扩展性(由多态保证)

接口与抽象类的关系

抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象

接口:
成员变量:只可以常量

成员方法:只可以抽象

抽象能被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。

接口被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。

四种权限修饰符下的访问权限

在这里插入图片描述

内部类

内部类可以访问外部类的成员,包括私有。外部类访问内部类,必须要先创建一个外部类的变量。
成员内部类:

// People.java
//外部类People
public class People {
    private String name = "LiLei";         //外部类的私有属性
    //内部类Student
    public class Student {
        String ID = "20151234";               //内部类的成员属性
        //内部类的方法
        public void stuInfo(){
            System.out.println("访问外部类中的name:" + name);
            System.out.println("访问内部类中的ID:" + ID);
        }
    }

    //测试成员内部类
    public static void main(String[] args) {
        People a = new People();     //创建外部类对象,对象名为a
        Student b = a.new Student(); //使用外部类对象创建内部类对象,对象名为b
        // 或者为 People.Student b = a.new Student();
        b.stuInfo();   //调用内部对象的suInfo方法
    }
}

如果是被static静态修饰符修饰的静态内部类,访问方式是:外部类名.内部类名 对象名 = new 外部类名.内部类名();
静态内部类:

// People.java
//外部类People
public class People {
    private String name = "LiLei";         //外部类的私有属性

/*外部类的静态变量。
Java 中被 static 修饰的成员称为静态成员或类成员。它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享。静态成员可以使用类名直接访问,也可以使用对象名进行访问。
*/
    static String ID = "510xxx199X0724XXXX";

    //静态内部类Student
    public static class Student {
        String ID = "20151234";               //内部类的成员属性
        //内部类的方法
        public void stuInfo(){
            System.out.println("访问外部类中的name:" + (new People().name));
            System.out.println("访问外部类中的ID:" + People.ID);
            System.out.println("访问内部类中的ID:" + ID);
        }
    }

    //测试成员内部类
    public static void main(String[] args) {
        Student b = new Student();   //直接创建内部类对象,对象名为b
        b.stuInfo();                 //调用内部对象的suInfo方法
    }
}

静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问。
如果外部类的静态成员与内部类的成员名称相同,可通过 类名.静态成员 访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过 成员名 直接调用外部类的静态成员。
创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名 = new 内部类();。

使用匿名内部类有个前提条件:必须继承一个父类或实现一个接口。
匿名内部类实现外部接口格式:

new.接口名或类名(){

需要重写的方法

}.调用方法;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值