注释
单行注释 //
多行注释 /* */
文档注释
/**
*每一行都有 *
*/
文档注释内可有参数信息
比如@author 作者名
@version 版本号
@param 参数名
标识符和关键字
- Java所有的组成部分都需要名字,类名,变量名以及方法名都被称为标识符
- 所有的标识符都要以字母,美元符号($) ,下划线(_) 开头
- 首字母之后可以是任意字母,美元符号($) ,下划线(_) ,或数字的任何字符
- 不能使用关键字
- 标识符是大小写敏感的
数据类型
-
java是一种强类型语言,要求变量的使用要严格符合规定,所有变量都必须限定以后才能使用
-
java的数据类型分为两大类
-
基本类型
- byte
- short
- int
- long
- float
- double
- char
- boolean
-
引用类型
- 类
- 接口
- 数组
-
拓展
-
最好完全避免使用浮点数进行比较
-
所有的字符本质还是数字
-
Unicode 编码 占 2字节 表 :(97 = a 65 = A) 可以表示65536个字符
-
转义字符 :\t 制表符 \n 换行符
-
String sa = new String("hello world"); String sb = new String("hello world"); System.out.println(sa==sb); String sc = "hello world"; String sd = "hello world"; System.out.println(sc==sd);
-
运行结果将会是false true
类型转换
低–>高
byte,short,char -> int ->long -> float -> double
- 从低到高会自动转换
- 从高到低要强制转换
- 不能对布尔值转换
- 不能把对象类型转换为不相干的类型
- 转换的时候可能存在内存溢出,或者精度问题
- 操作比较大的数的时候,注意溢出问题
- JDK7新特性,数字之间可以用下划线分割
变量 常量 作用域
-
类变量:static 修饰
-
实例变量:无static修饰,从属于对象;
如果不自行初始化,这个类型的默认值 0 0.0 布尔值是false 除了基本类型,其余的都是null;
-
局部变量:方法内的,必须声明和初始化值!
-
常量:使用static final 修饰
运算符小结
int a=10;
int b=20;
System.out.println(""+a+b);
System.out.println(a+b+"");
- 运算结果会是1020 和 30
用户交互类Scanner
next():
- 一定要读取到有效字符后才可以结束输入
- 对输入的有效字符之前遇到的空白,next()方法会自动将其去掉
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
- next()不能得到带有空格的字符串。
nextLine():
- 以回车Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符
- 可以获得空白
方法重载
-
方法重载就是在一个类中,有相同的函数名称,但形参不同的函数
-
方法重载的规则
- 方法名称必须相同
- 参数列表必须不同(个数不同、或者类型不同、参数的排列顺序不同)
- 方法的返回类型可以也可以不相同
- 仅仅返回类型不同不足以成为方法的重载
-
实现理论
- 方法名称相同时,编译器会根据调用方法的参数个数,参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器会报错
数组
数组的4个基本特点
-
数组的长度是确定的。一旦被创建,它的大小就是不可以改变的
-
其元素必须是相同类型,不允许出现混合类型
-
数组中的元素可以是任何数据类型,包括基本类型和引用类型
-
数组变量属于应用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象
类型数组对象本身是在堆中的
Java中的内存分析
稀疏数组
-
当一个数组中大部分元素为0,或者为同一值得数组是,可以使用稀疏数组来保存该数组。
-
稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素行和列及值记录在一个小规模的数组中,从而缩小程序的规模
-
如下图:左边是原始数组,右边是稀疏数组
面向对象编程(OOP)
-
面向对象的本质就是:以类的方式组织代码,以对象的组织(封装)数据
-
三大特性:
封装:属性私有,get、set
继承:extends,Object,子类拥有父类的全部特性,方法重写 , this,super,单继承
多态: 父类的引用指向子类的对象 Person person = new Student()
实例化这个类,通过new关键字
被static修饰的是和类一起加载的,类一存在static 就存在了
创建对象的内存分析
以下列代码作为分析
package 面向对象;
public class Pet {
public String name;
public int age;
public void shout(){
System.out.println("叫了一声");
}
}
package 面向对象;
public class Application {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name="旺财";
dog.age=3;
dog.shout();
System.out.println(dog.name);
System.out.println(dog.age);
Pet cat = new Pet();
}
}
引用变量:在栈里面就是个普通的引用变量名,真正指向的是堆中的具体对象,只是通过栈给他起了个名字
其中方法区也是堆的一部分。
小结一下
1.类与对象
- 类是一个模板:抽象,对象是一个实例:具体
2.方法
- 定义 调用!
3.对象的引用
-
引用类型: 基本类型(8)
-
对象是通过引用来操作的 : 栈 —>堆
4.属性:字段 成员变量
-
默认初始化:
-
数字: 0 0.0
-
字符:u0000
-
布尔:false
-
引用:null
5.对象的创建和使用
- 必须使用new关键字创造对象,还要有构造器 Person banana = new Person();
- 对象的属性 banana.name
- 对象的方法 banana.sleep()
6.类
- 静态的属性 属性
- 动态的行为 方法
封装
-
该露的露,该藏的藏
- 我们程序设计要追求 “高内聚,低耦合” 。 高内聚就是类的内部数据操作细节自己完成,不允许外部干涉,低耦合,金宝路少量的方法给外部使用
-
封装(数据的隐藏)
- 通常,应禁止直接访问一个对象种数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
意义
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统的可维护性增加了
属性私有,get/set 可以在set方法中做数据的合理性,安全性验证
继承
- 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
- extends 的意思是 “扩展” 。 子类是父类的扩展
- Java中类只有单继承,没有多继承!
- 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖,组合,聚合等。
- 继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
- 子类和父类之间,从意义上讲应该具有 “is a” 的关系
super()
- super调用父类的构造方法,必须在构造方法的第一行
- super必须只能出现在自类的方法或者构造方法中!
- super和this不能同时调用构造方法!
Vs this:
代表的对象不同:
this: 本身调用者这个对象
super:代表父类对象的应用
前提
this:没有继承也可以使用
super:只能在继承条件才可以使用
构造方法
this(); 本类的构造
super(); 父类的构造!
方法重写
父类可以new子类(父类的引用,指向子类的类型)
B b = new A();
方法的调用只和左边,定义的数据类型有关(静态方法)
方法重写后,要看new的谁,new谁,用得就是谁的方法(普通方法 )
重写:需要有继承关系子类重写父类的方法!
- 方法名必须相同
- 参数列表表虚相同
- 访问修饰符:范围可扩大 但不能缩小
- 抛出的异常:范围,可以被缩小 但不能扩大
重写,自诶和弗雷必须要一直;方法体不同!
为什么需要重写:
- 父类的功能 , 子类不一定需要,或者不一定满足!
多态
-
动态编译:类型:可扩展性
-
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
-
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)
-
多态存在的条件
- 有继承关系
- 子类重写父类的方法
- 父类引用指向子类的对象
public class Person {
public void run(){
System.out.println("run");
}
}
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Person();
//new Student();
//可以指向的引用类型就不确定了:父类的引用指向子类
//Student 能调用的方法都是自己的或继承父类的!
Student s1 = new Student();
//Person 父类型,可以指向子类,但是不能调用子类独有的方法!
Person s2 = new Student();
Object s3 = new Student();
s2.run();//子类重写了父类的方法,执行子类的方法(不重写的话执行的是run)
s1.run();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s1.eat();
}
}
多态注意事项
- 多态是方法的多态,属性没有多态
- 父类和子类,有联系 类型转换异常! ClassCastException!
- 存在条件:继承关系,方法需要重写,父类的引用指向子类对象! father f1 = new Son();
- static 方法,属于类,他不属于实例;
- final 常量 无法被改变,不能重写;
- private方法
instanceof
判断一个对象是什么类型
多一个子类好比较
public class Teacher extends Person{
}
public class Application {
public static void main(String[] args) {
//Object > String
//Object > Person > Teacher
//Object > Person > Student
Object object = new Student();
//System.out.println(X instanceof Y); // 能不能编译通过要看X能不能转换成Y类型,能的话才能通过 X所指向的实际类型是不是Y的子类型
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//False
System.out.println(object instanceof String);//False
System.out.println("============================");
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//False
//System.out.println(person instanceof String);//编译报错
System.out.println("============================");
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
//System.out.println(student instanceof Teacher);//编译报错
//System.out.println(student instanceof String);//编译报错
}
类型转换
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型,不用强制转换
- 把父类转换为子类,向下转型,强制转换
- 方便方法的调用,减少重复的代码!
抽象:封装、继承、多态! 抽象类 , 接口
static关键字
没有this的方法
静态变量,静态方法,可以直接在类中调用
在static方法内部不能调用非静态方法,不能访问非静态成员变量
在非静态方法内部可以直接调用static方法
静态变量被所有对象所共享,它当且仅当在类初次加载时会被初始化。
静态代码块
public class Person {
//2.赋初始值
{
System.out.println("匿名代码块");
}
//1.只执行一次
static{
System.out.println("静态代码块");
}
//3
public Person(){
System.out.println("无参构造");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("===========");
Person person2 = new Person();
}
}
静态导入包
import static java.lang.Math.random;
可以在类中直接用random()方法
抽象类
abstract,抽象方法 ,只有方法的名字,没有方法的实现
抽象类的所有方法,继承了他的子类,都必须要实现它的方法 (除非这个继承了他的子类也是个抽象类)
//abstract 抽象类 本质是一个类 extends: 单继承 (接口可以多继承)
public abstract class Action {
//约束~有人帮我们实现~
//abstract,抽象方法 ,只有方法的名字,没有方法的实现
public abstract void doSomething();
//1. 不能new这个抽象类,只能靠子类去实现它,约束
//2. 抽象类里面可以写普通方法
//3. 抽象方法必须在抽象类中
//抽象的抽象:约束~
}
接口
- 普通类:只有具体的实现
- 抽象类:具体实现和规范(抽象方法)都有!
- 接口:只有规范!自己无法写方法~专业的约束! 约束和实现分离:面向接口编程
两个接口一个实现类奉上
//抽象的思维~ Java 架构师~
//interface 定义关键字
public interface UserService {
//常量~ public static final
int AGE = 99;
//接口中的所有定义的方法其实都是抽象的 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
public interface TimeService {
void timer();
}
// 抽象类:extends~
// 一个类可以实现接口 implements 接口
// 实现了接口的类,就需要重写接口中的方法
// 多继承~利用接口实现多继承~
public class UserServiceImpl implements UserService,TimeService {
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
接口的作用:
- 约束
- 定义一些方法,让不同的人实现
- public abstract
- public static final
- 接口不能被实例化,接口中没有构造方法
- implements可以实现多个接口
- 必须要重写接口中的方法~
内部类
局部内部类
静态内部类
匿名内部类
异常机制
什么是异常
- 实际工作中,遇到的去看不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能失控的等。我们的程序在跑着,内存或硬盘可能满了,等等。
- 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是Exception,意思是例外。
三种类型的异常
- 检查型异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员符啊遇见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单的忽略。
- 运行时异常:运行时异常是可能被程序员避免的异常。与检查性质相反,运行式异常可以在编译时被忽略。
- 错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
-
Error类对象有Java虚拟机生成并抛出,大多数错误跟我们写的没关系
-
Java虚拟机运行错误,比如内存溢出 栈溢出。这种异常发生时,JVM一般会选择线程终止
-
在虚拟机试图执行应用时,突然发现类找不到了,类定义错误了,它就会抛出一些错误,这些错误我们写代码的时候根本不可能觉察得到,因为它不在应用程序的控制范围之内,绝大多数是程序运行时不允许出现的状况。
-
抛出异常
-
捕获异常
-
异常处理五个关键字
- try,catch,finally,throw,throws
用try{}块包围可能出现异常的代码块
catch(想要捕获的异常类型){} 捕获异常后执行的语句
finally{}程序无论出不出现异常,都会去执行finally里面的代码
finally{} 可以不要finally
假设要捕获多个异常:从小到大去捕获!
idea中 Ctrl+Alt+T 快捷键可以选择使用什么环绕
主动抛出异常 throw throws
throw + new 一个异常();
-
主动的抛出异常,一般在方法中使用
-
假设这个方法中,处理不了这个异常。就从方法上抛出异常
throws 异常类型
算数异常属于运行时异常,正常情况下不需要程序主动抛出,它自己就会抛出。
在调用抛出异常的方法时,在main中使用try catch环绕,程序会正常的往下执行,不过在mian中不使用try catch环绕,程序遇到错误直接停止!
package com.exception;
public class Test2 {
public static void main(String[] args) {
new Test2().test(1,0);
System.out.println("往下走了嘛");
System.out.println("往下走了哦");
}
public void test(int a,int b) throws ArithmeticException{
System.out.println(a/b);
}
}
程序遇到异常后即停止
package com.exception;
public class Test2 {
public static void main(String[] args) {
try {
new Test2().test(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
System.out.println("往下走了嘛");
System.out.println("往下走了哦");
}
public void test(int a,int b) throws ArithmeticException{
System.out.println(a/b);
}
}
程序继续往下执行了
自定义异常
用户自定义异常类,只需要继承Exception类即可