Java面向对象
初识面向对象
面向过程&面向对象
面向过程
步骤清晰简单,第一步做什么,第二步做什么……
适合处理简单问题
面向对象
物以类聚,分类的思维模式,首先解决问题是需要那些分类。
适合处理复杂问题,如多人协作的问题
对于描述复杂的事物,宏观上需要用面向对象的思路来分析,对于具体的微观操作,仍需要面向过程的思路去处理
什么是面向对象
面向对象编程(Object-Oriented Programming,OPP)
面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。
从认识的角度,先有对象后有类。对象,是具体的事物;类,是抽象的,是对对象的抽象
从代码运行角度,先有类后有对象。类是对象的模板。
对象的创建分析
类与对象的关系
类是一种抽象的数据类型,它是对某一类事物的整体描述/定义,但是并不能代表某一个具体事物
对象是抽象概念的具体实例
创建与初始化对象
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
类中的构造器也称为构造方法,是在创建对象的时候必须调用的。并且构造器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回值,void也不行
面向对象三大特性
封装
- 该露的露,该藏的藏
- 我们程序设计追求“高内聚,低耦合”。高内聚:类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。 - 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这成为信息隐藏。
=> 属性私有(private)并提供一些public的get、set方法
继承
- 继承的本质是对某一批类的抽象
- extands的意思是“扩展”。子类是父类的扩展,可以继承父类的所有方法
- 私有的(private)的内容,是不能继承的
- IDEA Ctrl+H可以查看类继承关系
- is a关系
public对外部完全可见。proteced对本包和所有子类可见。private仅对本类可见。默认对本包可见,不需要修饰符。
super
默认与this使用本类的方法,super使用超类的方法
public void test(){
print();//调用本类的print方法
this.print();//调用本类的print方法
super.print();//调用超类(父类)的print方法
}
调用父类的构造器,必须在构造方法的第一个。
只能在继承条件下才可以使用。
方法重写
重载 ≠ 重写
重写都是方法的重写,与属性无关
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。
多态
多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
父类的引用指向子类,若子类重写了父类的方法,执行子类的方法
父类型可以指向子类,但是不能调用子类独有的方法
子类型能调用的方法是自己的或继承父类的
抽象类和接口
抽象类
abstract 抽象修饰符,可抽象类和方法
类 extends:单继承 (但接口可以多继承)
抽象方法只有方法名字,没有方法的实现
抽象类无法new,只能靠子类去实现它:约束
抽象类中可以写普通的方法
抽象方法必须在抽象类中
接口
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范!自己无法写方法(专业的抽象) => 约束和实现分离:面向接口编程
声明类的关键字是class,声明接口的关键字是interface
简单代码示例:
// interface 定义的关键字 , 接口都需要有实现类
public interface UserService {
//接口中的所有定义其实都是抽象的 public abstract
void run();
public abstract void run(String name); //public abstract 是灰色的,不用写也是默认该类型
//接口内可以生成常量 public static final
int AGE = 99;
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
public interface TimeService {
void timer();
}
//抽象类:extends
// 类可以实现接口 implement 接口
//实现了接口的 类,就需要 重写 接口中的方法
//多继承 利用接口实现多个继承
public class UserServiceImpl implements UserService,TimeService{
@Override
public void run() {
}
@Override
public void run(String name) {
}
@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() {
}
}
作用:
- 1.约束
- 2.定义一些方法,让不同的人去实现
- public abstract
- public static final
- 接口不能被实例化,接口中没有构造方法
- implements 可以实现多个接口
- Impl类必须要重写接口中的方法(impl首字母大写) (@Override => 重写)
内部类及OOP实战
内部类就是在一个类的内部再定义一个类。
- 成员内部类
- 成员内部类可以使用外部类的私有属性和方法(public) - 静态内部类
- 无法访问非静态的属性(public static) - 局部内部类
- 方法内的类 - 匿名内部类
- 没有名字去初始化类,不用将实例保存在变量中
内部类代码示例:
public class innerClass {
public static void main(String[] args) {
var clock = new TalkingClock(1000,true);
clock.start();
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}
class TalkingClock{
private int interval;
private boolean beep;
//alt+insert构造函数,一键构造类构造器
public TalkingClock(int interval, boolean beep) {
this.interval = interval;
this.beep = beep;
}
public void start(){
var listener = new TimePrinter();
var timer = new Timer(interval,listener);
timer.start();
}
public class TimePrinter implements ActionListener{
@Override
public void actionPerformed(ActionEvent event) {
System.out.println("At the tone, the time is" + Instant.ofEpochMilli(event.getWhen()));
if(beep) Toolkit.getDefaultToolkit().beep();
}
}
public void start2(){
//声明局部内部类时不能有访问说明符(即public或private)
// 局部类对外部世界完全隐藏,即使TalkingClock类中的其他代码也不能访问他,除start2外,没有任何方法知道TimePrinter2类的存在
class TimePrinter2 implements ActionListener{
public void actionPerformed(ActionEvent event){
System.out.println("At the tone, the time is" + Instant.ofEpochMilli(event.getWhen()));
if(beep) Toolkit.getDefaultToolkit().beep();
}
}
}
/*
一般的,匿名类语法如下:
new SuperType(construction parameters)
{
inner class methods and data
}
//SuperType 可以是接口也可以是类,如果是接口要实现接口,如果是类需要扩展这个类
//匿名内部类没有类名。因此没有构造器
//内部类实现一个接口,不能有任何构造参数,但依然需要小括号
new InterfaceType(){
methods and data
}
*/
public void start(int interval, boolean beep){
var listener = new ActionListener()//创建一个类的新对象
{
//实现的方法在括号内定义-> 实现了ActionListener接口
public void actionPerformed(ActionEvent event)
{
System.out.println("At the tone, the time is" + Instant.ofEpochMilli(event.getWhen()));
if(beep) Toolkit.getDefaultToolkit().beep();
}
};
var timer = new Timer(interval, listener);
if(beep) Toolkit.getDefaultToolkit().beep();
timer.start();
}
//运用lamda表达式
public void start2(int interval, boolean beep){
var timer = new Timer(interval, event->{
System.out.println("At the tone, the time is" + Instant.ofEpochMilli(event.getWhen()));
if(beep) Toolkit.getDefaultToolkit().beep();
});
timer.start();
}
}
静态内部类代码示例:
public class staticInnerClass {
public static void main(String[] args) {
var values = new double[20];
for(int i = 0; i<values.length; i++)
values[i] = Math.random()*100;
ArrayAlg.Pair p = ArrayAlg.minmax(values);
System.out.println("min = " + p.getFirst());
System.out.println("max = " + p.getSecond());
}
}
//使用内部类最吸引人的原因是:
//每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对内部类都没有影响。
//内部类有效的实现了“多重继承”。也就是说,内部类允许继承多个非接口类型(类或者抽象类)。
//使用内部类还可以获得其他一些特性
//1. 内部类可以有多个实例,每个实例都有自己的状态信息,并且与外围类对象的信息相互独立。
//2. 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类。
//3. 创建内部类对象的时刻并不依赖于外围类对象的创建。
//4. 内部类并没有令人迷惑的 “is-a”关系;它就是一个独立的实体。
class ArrayAlg
{
//静态内部类Pair
//为了把一个类隐藏在另一个类的内部,并不需要内部类有外围类对象的一个引用。(不需要外围的信息)
public static class Pair {
private double first;
private double second;
public Pair(double first, double second) {
this.first = first;
this.second = second;
}
public double getFirst() {
return first;
}
public double getSecond() {
return second;
}
}
public static Pair minmax(double[] values)
{
double min = Double.POSITIVE_INFINITY;
double max =Double.NEGATIVE_INFINITY;
for (double v: values)
{
if (min>v) min = v;
if (max<v) max = v;
}
return new Pair(min,max);
}
}
static补充
静态代码块首先执行并只运行一次,匿名代码块后执行且每new一个对象就会执行一次,后执行构造方法
public class Person {
public Person(){
System.out.println("构造方法");
}
//第二执行,且能执行多次 => 用于赋初始值 跟对象同时产生
{
System.out.println("匿名代码块");
}
//最早执行且执行一次
static {
System.out.println("静态代码块");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("====================");
Person person2 = new Person();
System.out.println("====================");
Person person3 = new Person();
}
}
/*
输出结果为:
静态代码块
匿名代码块
构造方法
====================
匿名代码块
构造方法
====================
匿名代码块
构造方法
*/
静态导入包补充
//静态导入包
import static java.lang.Math.random;
public class Test {
public static void main(String[] args) {
//若无静态导入包
System.out.println(Math.random());
//静态导入包后可将Math省略
System.out.println(random());
}
}
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Instant;
import javax.swing.*;
public class innerClass {
public static void main(String[] args) {
var clock = new TalkingClock(1000,true);
clock.start();
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}
class TalkingClock{
private int interval;
private boolean beep;
//alt+insert构造函数,一键构造类构造器
public TalkingClock(int interval, boolean beep) {
this.interval = interval;
this.beep = beep;
}
public void start(){
var listener = new TimePrinter();
var timer = new Timer(interval,listener);
timer.start();
}
public class TimePrinter implements ActionListener{
@Override
public void actionPerformed(ActionEvent event) {
System.out.println("At the tone, the time is" + Instant.ofEpochMilli(event.getWhen()));
if(beep) Toolkit.getDefaultToolkit().beep();
}
}
public void start2(){
//声明局部内部类时不能有访问说明符(即public或private)
// 局部类对外部世界完全隐藏,即使TalkingClock类中的其他代码也不能访问他,除start2外,没有任何方法知道TimePrinter2类的存在
class TimePrinter2 implements ActionListener{
public void actionPerformed(ActionEvent event){
System.out.println("At the tone, the time is" + Instant.ofEpochMilli(event.getWhen()));
if(beep) Toolkit.getDefaultToolkit().beep();
}
}
}
/*
一般的,匿名类语法如下:
new SuperType(construction parameters)
{
inner class methods and data
}
//SuperType 可以是接口也可以是类,如果是接口要实现接口,如果是类需要扩展这个类
//匿名内部类没有类名。因此没有构造器
//内部类实现一个接口,不能有任何构造参数,但依然需要小括号
new InterfaceType(){
methods and data
}
*/
public void start(int interval, boolean beep){
var listener = new ActionListener()//创建一个类的新对象
{
//实现的方法在括号内定义-> 实现了ActionListener接口
public void actionPerformed(ActionEvent event)
{
System.out.println("At the tone, the time is" + Instant.ofEpochMilli(event.getWhen()));
if(beep) Toolkit.getDefaultToolkit().beep();
}
};
var timer = new Timer(interval, listener);
if(beep) Toolkit.getDefaultToolkit().beep();
timer.start();
}
//运用lamda表达式
public void start2(int interval, boolean beep){
var timer = new Timer(interval, event->{
System.out.println("At the tone, the time is" + Instant.ofEpochMilli(event.getWhen()));
if(beep) Toolkit.getDefaultToolkit().beep();
});
timer.start();
}
}
public class staticInnerClass {
public static void main(String[] args) {
var values = new double[20];
for(int i = 0; i<values.length; i++)
values[i] = Math.random()*100;
ArrayAlg.Pair p = ArrayAlg.minmax(values);
System.out.println("min = " + p.getFirst());
System.out.println("max = " + p.getSecond());
}
}
//使用内部类最吸引人的原因是:
//每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对内部类都没有影响。
//内部类有效的实现了“多重继承”。也就是说,内部类允许继承多个非接口类型(类或者抽象类)。
//使用内部类还可以获得其他一些特性
//1. 内部类可以有多个实例,每个实例都有自己的状态信息,并且与外围类对象的信息相互独立。
//2. 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类。
//3. 创建内部类对象的时刻并不依赖于外围类对象的创建。
//4. 内部类并没有令人迷惑的 “is-a”关系;它就是一个独立的实体。
class ArrayAlg
{
//静态内部类Pair
//为了把一个类隐藏在另一个类的内部,并不需要内部类有外围类对象的一个引用。(不需要外围的信息)
public static class Pair {
private double first;
private double second;
public Pair(double first, double second) {
this.first = first;
this.second = second;
}
public double getFirst() {
return first;
}
public double getSecond() {
return second;
}
}
public static Pair minmax(double[] values)
{
double min = Double.POSITIVE_INFINITY;
double max =Double.NEGATIVE_INFINITY;
for (double v: values)
{
if (min>v) min = v;
if (max<v) max = v;
}
return new Pair(min,max);
}
}
内存分析
堆
存放new的对象和数组
可以被所有的线程共享,不会存放别的对象引用
栈
存放基本变量类型(包含这个基本类型的具体数值)
引用对象的变量(会放在这个引用堆的具体地址)
方法区
可以被所有线程共享
包含了所有的class和static变量
Arrays类
数组的工具类 java.util.Arrays
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注:是“不用”而不是“不能”)
具有以下功能:
- 给数组赋值:fill,将指定值分配给指定范围内的每个元素
- 对数组排序:sort,按升序排序
- 比较数组:equals
- 查找数组元素:binarySearch,二分查找
- 返回数组内容的字符串表示形式:toString
- 根据数组内容返回哈希吗:hashCode
- 将指定数组范围内元素赋值到新数组:copyOfRange
- 返回数组支持的固定大小的列表:asList
Java方法详解
方法基本概念
Java方法是语句的集合,它们在一起执行一个功能。
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
设计方法的原则:
方法的本意是功能块,是实现某个功能的语句块的集合。设计方法时,最好保持原子性,即一个方法只完成一个功能,有利于后期的拓展。
方法的命名规则:
首字母小写驼峰原则
简单示例
public class Demo01 {
//main 方法
public static void main(String[] args) {
int sum = add(1,2);
System.out.println(sum);
}
//加法 add 方法
public static int add(int a, int b){
return a+b;
}
}
方法的定义及调用
方法的定义
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;//void 无须return。返回时要符合返回值类型。
}
- 修饰符:是可选的,定义该方法的访问类型
- 返回值类型:方法可能会有返回值。returnValueType 是方法的返回值的数据类型。有些方法执行所需的操作,但没有返回值。这种情况下,returnValueType 是关键字void。
- 方法名:方法的实际名称,符合方法的命名规则即可。
- 参数类型:参数是可选的,方法可以不含任何参数。
- 形参:在方法被调用时用于接收外界输入的数据。(定义作用)
- 实参:调用方法时实际传给方法的数据。 - 方法体:方法体包含具体的语句,定义该方法的功能。
方法的调用
调用方法:对象名.方法名(实参列表)
Java支持两种调用方法的方式,根据方法是否返回值来选择。
- 当方法返回一个值的时候,方法调用被当做一个值。例如:
int larger = max(30,40);
- 如果方法返回值是void,方法调用一定是一条语句。
System.out.println("xxx");
Java都是值传递
方法重载
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
方法重载的规则:
- 方法名必须相同
- 参数列表必须不同(个数不同,或类型不同,或参数排列顺序不同等)
- 方法的返回类型可以相同也可以不同
- 仅仅返回类型不同不足以成为方法的重载
实现理论:
方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如匹配失败,则报错。
简单示例:
public class Demo01 {
//main 方法
public static void main(String[] args) {
int sum = add(1,2);
System.out.println(sum);//输出3
double sum2 = add(1.0,5.0);
System.out.println(sum2);//输出6.0
}
//加法 add 方法
public static int add(int a, int b){
return a+b;
}
//加法 add 方法
public static double add(double a, double b){
return a+b;
}
}
命令行传参
在运行一个程序时在传递给它消息。依靠传递命令行参数给main()函数实现。
可变参数
在方法声明中,在指定参数类型后加一个省略号。
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
- 简单示例:
public class Demo03 {
public static void main(String[] args) {
Demo03 demo03 = new Demo03();
demo03.test(4,5,7,9,5,78);
}
public void test(int x,int ...i){
System.out.println(x);
System.out.println(i[0]);
System.out.println(i[2]);
System.out.println(i[3]);
}
}
Java流程控制
用户交互Scanner
包:java.util.Scanner
通过Scanner类来获取用户的输入
基本语法:
Scanner s = new Scanner(System.in)
//IO流的类如果不关闭会一直占用资源
//养成用完就关掉的习惯
scanner.close();
- next():
- 一定要读到有效字符后才能结束输入。
- 对输入有效字符之前的空白,会自动去掉。
- 只有输入有效字符后才能将其后面输入的空白作为分隔符或结束符。
- next()不能得到带空白的字符串。 - nextLine():
- 以Enter为结束符
- 可以获得空白的字符串
简单Scanner程序:
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
//创建一个扫描器对象,接受键盘数据
Scanner scanner = new Scanner(System.in);
double sum = 0;
int m = 0;
System.out.println("请输入任意个数字,并以任意字符结束");
//通过while循环判断是否还有输入,并进行统计
//scanner.hasNext... 判断是否有...输入
while (scanner.hasNextDouble()){
double x = scanner.nextDouble();
m++;
sum +=x;
}
System.out.println("和为:"+sum);
//IO流的类如果不关闭会一直占用资源
//养成用完就关掉的习惯
scanner.close();
}
}
顺序结构
除非特别指明,否则就按照顺序一句一句执行。
基本算法结构。
选择结构
if单选择结构
if(condition) statement
if双选择结构
if(condition) statement1 else statement2
if多选择结构
一条指令成功执行,直接跳过剩下未判断的语句,跳出if结构
if(condition) statement1
else if(condition) statement2
else if(condition) statement3
.
.
.
else statementn
嵌套的if结构
if(condition){
statement1;
if(condition){
statement2
//……
}
}
switch多选择结构
case具有穿透现象,如果case内无break会继续向下执行。
switch语句中的变量可以是byte、short、int、char或String
switch(expression){
case value1:
statement1;
break;//可选
case value2:
statement2;
break;//可选
case value3:
statement3;
break;//可选
//……
default:
statementn;
}
循环结构
while循环
while(condition) statement
当条件为true时,while循环执行一条语句(或一块语句)。
如果开始时循环条件的值就位false,那么while循环一次也不执行。
除非特定需要,避免造成死循环。
do…while循环
do statement while(condition)
这种循环语句先执行语句,然后再检测循环条件。如果为true,就重复执行语句,然后再次检测循环条件。
for循环(确定循环)
for(初始化;condition;更新)
statement;
简单for循环程序
public class Demo01 {
public static void main(String[] args) {
//初始化//条件判断//迭代
for(int i = 1; i <= 10; i++){
System.out.println(i);
}
}
}
增强for循环(for each循环)
可以依次处理数组(或者其他元素集合)中的每个元素,而不必考虑指定下标值。
for(variable : collection) statement
for each 输出二维数组
public class Demo02 {
public static void main(String[] args) {
double [][] a = new double [3][4];
for (int i = 0; i<a.length; i++){
for (int j = 0; j<a[i].length; j++){
a[i][j] = Math.random()*100;
a[i][j] = (double)Math.round(a[i][j]*100)/100;
}
}
//for each 输出二维数组
for(double[] row : a) {
for (double value : row) {
//do something with value
System.out.print(value+"\t");
}
System.out.println();
}
//快速输出二维数组的元素列表
System.out.println(Arrays.deepToString(a));
}
}
break&continue
- break
在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。
- continue
用在循环语句体中,用于终止某次循环过程,跳过循环体中未执行的语句,接着进行下一次是否执行循环的判断。
Java基础
注释
注释并不会被执行,是给人看的
- 单行注释 使用 //
其注释内容从 // 开始到本行结尾
- 多行注释 使用 /* 和 */ 注释界定符
public class helloworld {
public static void main(String[] args) {
//这是注释
/* 这也是
注释
*/
System.out.println("Hello world!");
}
}
- 文档注释 JavaDoc
javadoc 命令是用来生成自己API文档的
- 参数信息
- @author 作者名
- @version 版本号
- @since 指明需要最早使用的jdk版本
- @param 参数名
- @return 返回值情况
- @throws 异常抛出情况
/**
* This is the first sample program
* @version 11
* @author Tagiri
*/
/**
* ░░░░░░░░░░░░░░░░░░░░░░░░▄░░
* ░░░░░░░░░▐█░░░░░░░░░░░▄▀▒▌░
* ░░░░░░░░▐▀▒█░░░░░░░░▄▀▒▒▒▐
* ░░░░░░░▐▄▀▒▒▀▀▀▀▄▄▄▀▒▒▒▒▒▐
* ░░░░░▄▄▀▒░▒▒▒▒▒▒▒▒▒█▒▒▄█▒▐
* ░░░▄▀▒▒▒░░░▒▒▒░░░▒▒▒▀██▀▒▌
* ░░▐▒▒▒▄▄▒▒▒▒░░░▒▒▒▒▒▒▒▀▄▒▒
* ░░▌░░▌█▀▒▒▒▒▒▄▀█▄▒▒▒▒▒▒▒█▒▐
* ░▐░░░▒▒▒▒▒▒▒▒▌██▀▒▒░░░▒▒▒▀▄
* ░▌░▒▄██▄▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒▒
* ▀▒▀▐▄█▄█▌▄░▀▒▒░░░░░░░░░░▒▒▒
* 单身狗就这样默默地看着你,一句话也不说。
*/
标识符
Java 所有的组成部分都需要名字。
类名、变量名以及方法名都被称为标识符。
关键字
关键字 | 含义 |
---|---|
abstract | 表明类或者成员方法具有抽象属性 |
assert | 断言,用来进行程序调试 |
boolean | 基本数据类型之一,声明布尔类型的关键字 |
break | 提前跳出一个块 |
byte | 基本数据类型之一,字节类型 |
case | 用在switch语句之中,表示其中的一个分支 |
catch | 用在异常处理中,用来捕捉异常 |
char | 基本数据类型之一,字符类型 |
class | 声明一个类 |
const | 保留关键字,没有具体含义 |
continue | 回到一个块的开始处 |
default | 默认,例如,用在switch语句中,表明一个默认的分支。Java8 中也作用于声明接口函数的默认实现 |
do | 用在do-while循环结构中 |
double | 基本数据类型之一,双精度浮点数类型 |
else | 用在条件语句中,表明当条件不成立时的分支 |
enum | 枚举 |
extends | 表明一个类型是另一个类型的子类型。对于类,可以是另一个类或者抽象类;对于接口,可以是另一个接口 |
final | 用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变,用来定义常量 |
finally | 用于处理异常情况,用来声明一个基本肯定会被执行到的语句块 |
float | 基本数据类型之一,单精度浮点数类型 |
for | 一种循环结构的引导词 |
goto | 保留关键字,没有具体含义 |
if | 条件语句的引导词 |
implements | 表明一个类实现了给定的接口 |
import | 表明要访问指定的类或包 |
instanceof | 用来测试一个对象是否是指定类型的实例对象 |
int | 基本数据类型之一,整数类型 |
interface | 接口 |
long | 基本数据类型之一,长整数类型 |
native | 用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的 |
new | 用来创建新实例对象 |
package | 包 |
private | 一种访问控制方式:私用模式 |
protected | 一种访问控制方式:保护模式 |
public | 一种访问控制方式:共用模式 |
return | 从成员方法中返回数据 |
short | 基本数据类型之一,短整数类型 |
static | 表明具有静态属性 |
strictfp | 用来声明FP_strict(单精度或双精度浮点数)表达式遵循IEEE 754算术规范 |
super | 表明当前对象的父类型的引用或者父类型的构造方法 |
switch | 分支语句结构的引导词 |
synchronized | 表明一段代码需要同步执行 |
this | 指向当前实例对象的引用 |
throw | 抛出一个异常 |
throws | 声明在当前定义的成员方法中所有需要抛出的异常 |
transient | 声明不用序列化的成员域 |
try | 尝试一个可能抛出异常的程序块 |
void | 声明当前成员方法没有返回值 |
volatile | 表明两个或者多个变量必须同步地发生变化 |
while | 用在循环结构中 |
标识符注意点
- 所有的标识符都应该以字母、美元符或下划线开始
- 首字母后可以是字母、美元符、下划线或数字的任何字符组合
- 不能使用关键字作为变量名或方法名
- 标识符是大小写敏感的
数据类型
Java属于强类型语言,要求变量的使用要严格符合规定,所有变量都必须先定以后才能使用
必须为每一个变量声明一种类型
安全性高但运行速度较弱类型语言慢
八种基本类型(primitive type)
四种整型
类型 | 存储需求 | 取值范围 |
---|---|---|
int | 4字节 | ±2^31-1 |
short | 2字节 | ±2^15-1 |
long | 8字节 | ±2^63-1 |
byte | 1字节 | ±2^7-1 |
两种浮点类型
类型 | 存储需求 | 取值范围 |
---|---|---|
float | 4字节 | 有效位数为6~7位 |
double | 8字节 | 有效位数为15位 |
double类型的数值精度是float类型的两倍,因此称为双精度。
定义float类型时,要在数值后添加一个后缀F或f,例如:
float num=3.14f
没有后缀F的浮点数值(如3.14)总是默认为double类型。
所有的浮点数值计算都遵循IEEE 754规范。并存在表示溢出和出错情况的三个特殊的浮点数值:
- 正无穷大 Double.POSITIVE_INFINITY
- 负无穷大 Double.NEGATIVE_INFINITY
- NaN(不是一个数字) Double.NaN
不能通过如下检测一个特定值是否等于Double.NaN:
if(x == Double.NaN) //is never true
所有“非数值”的值都认为是不相同的。可通过如下方法判断:
if(Double.isNaN(x)) //check whether x is not a number
一种字符类型 char类型
char类型原本用于表示单个字符。如今,有些Unicode字符可以用一个char值描述,另外一些Unicode字符则需要两个char值。
char类型的字面量值要用单引号括起来。例如:‘A’ 。
码点(code point)是指与一个编码表中的某个字符对应的代码值。在Unicode标准中,码点采用十六进制书写,并加上前缀U+,例如U+0041就是拉丁字母A的码点。Unicode的码点可以分成17个代码平面(code plane)。第一个代码平面称为基本多语言平面(basic multilingual plane),包括码点从U+0000到U+FFFF的“经典”Unicode代码;其余的16个平面的码点为从U+10000到U+10FFFF,包括辅助字符(supplementary character)。
UTF-16 编码采用不同长度的编码表示所有Unicode码点。在基本多语言平面中。每个字符用16位表示,通常称为代码单元(code unit);而辅助字符编码为一对连续的代码单元。
在Java中,char类型描述了UTF-16编码中的一个代码单元。
转义字符 \t(制表) \n(换行) ……
一种表示真值的类型 boolean类型
boolean(布尔)类型有两个值:false 和 true,用来判定逻辑条件。整形值和布尔值之间不能进行相互转换。
基本类型拓展
public class demo1 {
public static void main(String[] args) {
//整数拓展: 进制 二进制0b 十进制 八进制0 十六进制0x
int i = 10;
int i2 = 010; //八进制0
int i3 = 0x10; //十六进制0x 0~9、A~F 16
System.out.println(i);
System.out.println(i2);
System.out.println(i3);
//浮点数拓展 BigDecimal 数学工具 类
//float 有限 离散 舍入误差 接近但不等于 -> 容易出错(出现误差)
//避免完全使用浮点数进行比较 -> 用BigDecimal 数学工具 类
float f = 0.1f; // 0.1
double d = 1.0/10; // 0.1
double d2 = 0.1;
System.out.println(f == d); //false
System.out.println(f == d2); //false
float f1 = 121312312334343434343433333333341231223f;
float f2 = f1 + 1;
System.out.println(f1 == f2); //true
//字符拓展
char c1 = 'a';
char c2 = '中';
System.out.println(c1);
System.out.println((int)c1); //强制转换 97
System.out.println(c2);
System.out.println((int)c2); //强制转换 20013
// 所有的字符本质还是数字
// 编码 Unicode 表:97 = a 2字节 0~65536个字符
// 区间 U0000 UFFFF
char c3 = '\u0061';
System.out.println(c3); // a
String sa = new String("hello");
String sb = new String("hello");
System.out.println(sa == sb); //false
String sc = "hello";
String sd = "hello";
System.out.println(sc == sd); //true
}
}
引用类型(reference type)
类
接口
数组
类型转换
因为Java是强类型语言,所以要进行有些运算的时候,需要用到类型转换。
低 --------------------------------------------------------------- > 高
byte、short、char - > int - > long - > float - > double
在运算过程中,不同类型的数据先转化为同一类型,然后再进行运算。
- 强制转换 (类型)变量名 由高到低
- 自动转换 由低到高
注意点
1.不能对布尔值进行转换
2.不能把对象类型转换为不相干的类型
3.在把高容量转到低容量的时候,强制转换
4.转换时可能存在内存溢出,或精度问题
System.out.println((int)23.7); //23
System.out.println((int)-45.89f); //-45
char c ='a';
int d = c + 1;
System.out.println(d); //98
System.out.println((char)d); //b
int money = 10_0000_0000;
int years = 20;
int total = money * years; //计算时候结果溢出了 -1474836480
System.out.println(total);
long total2 = money * years; //默认是int,在转换之前已经出现问题了 -1474836480
System.out.println(total2);
long total3 = money *((long)years); //先把一个数转化为long 20000000000
System.out.println(total3);
变量
变量就是可以变化的量,常量就是值不变的变量。
Java 变量时程序中最基本的存储单元,其要素包括变量名、变量类型和作用域。
声明变量
- 在 Java 中,每个变量都有一个类型。在声明变量时,先指定变量的类型,然后是变量名。
- 变量名中所有的字符都是有意义的,并且大小写敏感。长度基本没有限制
- 不能使用 Java 保留字作为变量名
- 通过关键词 final 声明常量
变量初始化
-
声明一个变量之后,必须用赋值语句对变量进行显式初始化,千万不要使用未初始化的变量的值。
-
在 Java 中可以将声明放在代码中的任何地方。
-
变量的声明尽可能地接近变量第一次使用的地方(良好的程序编写风格)。
变量作用域
public class demo3 {
static int all = 0; //类变量
String str = "hello world"; //实例变量
public void method(){
int i = 0 ; //局部变量
}
}
类变量
需要加关键词 static 静态的 (修饰符)
实例变量
和类变量类似,但无 static 关键词
从属于对象
如果不自行初始化,则是这个类型的默认值 0 或 0.0 或 u0000 或 false(布尔) 或 null(引用类型)
demo3 d3 = new demo3();
System.out.println(d3.str);
局部变量
必须声明和初始化值,作用域在方法内
变量的命名规范
- 所有变量、方法、类名:见名知意
- 类成员变量:首字母小写和驼峰原则:lastName 除了第一个单词以外,后面的单词首字母大写
- 局部变量: 首字母小写和驼峰原则
- 常量:大写字母和下划线:MAX_VALUE
- 类名:首字母大写和驼峰原则:Man,GoodMan
- 方法名:首字母小写和驼峰原则:run()、runRun()
运算符
基本运算符
-
算数运算符:+、-、*、/、%、++、–
-
赋值运算符 :=
-
关系运算符 :>、<、>=、<=、==、!=、instanceof
-
逻辑运算符:&&、||、!
-
位运算符: 效率高
- & and
- | or
- ^ xor 相同为0,不同为1
- ~ not
- “>>” 左移
- << 右移
- “>>>” 用 0 填充高位
-
条件运算符: ?:
-
跨站赋值运算符:+=、-=、*=、/=
数学函数与常量
- Math.sqrt(x)
- Math.pow(x,a)
- 三角函数:sin、cos、tan、atan、atan2
- 指数函数与对数函数:exp、log、log10
- 常量:Math.PI - >π 、Math.E - > e
字符串
Java 没有内置的字符串类型,而是在标准 Java 类库提供了一个预定义类,叫做String。每个用双引号括起来的字符串都是 String 类。
子串
String 类的 substring 方法可以从一个较大的字符串提取出一个子串。例如:
创建一个字符 “Hel” 组成的字符串
String greeting = "Hello";
String s = greeting.substring(0,3);
拼接
Java 语言允许使用 + 号连接(拼接)两个字符串。
public static void main(String[] args) {
// ctrl + d 复制当前行到下一行
int a = 10;
int b = 25;
//注意区别
System.out.println(a+b+"");//35
System.out.println(""+a+b);//1025
System.out.println(a+""+b);//1025
}
不可变字符串
String 类没有提供修改字符串中某个字符的方法。
若想将 greeting 的内容修改为 help ,不能直接改变 greeting 。
但可通过保留部分子串,再与希望替换的字符拼接。
greeting = greeting.substring(0,3) + "p";
检测字符串是否相等
可以使用 equals 方法检测两个字符串是否相等。对于表达式:
s.equals(t);
如果字符串 s 与字符串 t 相等,则返回 true ;否则,返回 false 。
要想检测两个字符串是否相等,且不考虑大小写,可以使用 equalsIgnoreCase 方法。
"HELLO".equalsIgnoreCase("hello");
包机制
为了更好地组织类, Java提供了包机制,用于区别类名和命名空间。
一般利用公司域名倒置作为包名:
- 例如:www.baidu.com
- 包名为:com.baidu.www
为了能够使用某一个包的成员,我们需要在 Java 程序中明确导入该包。使用 “import” 语句即可
import package1[.package2…].(classname|*);
Java入门
Java历史
1972年C语言诞生
- 贴近硬件,运行极快,效率极高
- 操作系统、编译器、数据库、网络系统
- 具有指针和内存管理,但不兼容各平台,需要在不同平台编写C库
1982年C++诞生
- 面向对象
- 兼容C
- 注重图形领域和游戏方面
Java诞生
- 语法类C
- 无指针、无内存管理
- 具有可移植性,跨平台 JVM(虚拟机)
- 面向对象
初生
- 图形界面的程序(Applet) - > 微软使用Java
- 98年 Java 2
- Java 2 标准版(J2SE) 桌面领域
- Java 2 移动版(J2ME) 手机领域
- Java 2 企业版(J2EE) 服务器领域
发展
- 应用服务器: Tomcat、Jetty、Jboss、Websphere、weblogic
- Web开发: Spring、myBatis、Hibernate、Struts
- 开发工具: Eclipse、intellij idea、Netbean
- 构建工具: Ant、Maven、Jekins
- 2006: Hadoop 大数据领域
- 2008: Android 手机端 - >谷歌
Java特性和优势
- 简单性 C++语法纯净版
- 面向对象 万物皆对象
- 可移植性 write once, run anywhere 跨平台性
- 高性能性 接近C++的效率
- 分布式 URL
- 动态性 基于反射获得动态性
- 多线程 同时看视频、听音乐、打游戏
- 安全性、健壮性 防病毒、防篡改、省掉指针、内存检查
Java三大版本
-
JavaSE: 标准版(桌面程序、控制台开发)
- 基础 -
JavaME: 嵌入式开发(手机、小家电)
- 差不多死了 -
JavaEE: 企业级开发(web端,服务器开发)
- 基本就业方向
JDK、JRE、JVM
- JDK: java开发者工具
- JRE: java运行时环境
- JVM: java虚拟机
JDK包含JRE、JVM
JRE包含JVM
Java开发环境搭建
- 主流 JAVA JDK8
cmd中 java -version 检查是否配置JDK
Java程序运行机制
- 编译型 .java编译后成为 .class文件 加载进JVM 进行校验后 进入解释器 最后到操作系统平台 执行
- 解释型 速度要求不高 网页 java script
IDEA
IDE是什么
集成开发环境
集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具。
IDEA
简单写法
psvm - > public static void main(String[] args)
sout - > System.out.println();
后续补充