本文目录
JAVA基础DAY2
Scanner对象
java.util.Scanner是Java5的新特征,我们通过Scanner类获取用户输入。
基本语法:
Scanner s = new Scanner(System.in);
通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasNextLine()来判断是否还有输入的数据。
- next():
- 一定要读取到有效字符才可以结束
- 对输入有效字符前的空白,next()方法自动去掉
- 只有输入有效字符后才将其后面输入的空白作为分隔符或结束符
- next()不能得到带有空格的字符串
- nextLine():
- 以\n为结束符,返回换行符之前的所有字符
- 可以获得空白
流程控制
和C++一毛一样,略
方法
Java方法是语句的集合,在一起执行一个功能
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
方法重载
函数名相同,参数不同
命令行传参
有时候希望运行一个程序时再传递给它消息,要靠命令行参数给main()实现。
package Scanner;
public class Demo01 {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++){
System.out.println("args["+i+"]"+args[i]);
}
}
}
因为包含了package Scanner,所以必须在Scanner的上一层目录执行该程序
可变参数
JDK1.5之后,Java支持传递同类型的可变参数给一个方法
在方法声明中,在指定参数类型后加一个省略号(…)
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数,任何普通的参数必须在它之前声明。
public class Demo01 {
public static void main(String[] args) {
Demo01 demo01 = new Demo01();
demo01.printMax(1,2,3);
//demo01.printMax(new double[]{1,2,3}) also correct
}
public void printMax(double... nums)
{
if(nums.length==0)
{
System.out.println("no nums!");
return;
}
double max=-1e9;
for (double num : nums)
{
if(num>max)
max = num;
}
System.out.println("The biggest num in nums is :"+max);
}
}
数组
声明方法
// 1.声明
int[] arr; //首选声明方法
int arr[]; //可以,但是不要
// 2.创建一个数组
arr = new int[10];
数组变量是引用类型,数组也可以看成是对象,数组中每个元素相当于该对象的成员变量,数组本身就是对象,Java的对象在堆中,因此数组无论保存原始类型还是其他对象类型,数组对象本身在堆中。
多维数组
int[][] arr = {{1,2},{2,3}};
int[][] arr = new int[2][2];
Arrays类
- 数组的工具类java.util.Arrays
- Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而"不用"使用对象来调用(注意是“不用”而非“不能”)
- 常用方法:
- 赋值:fill()
- 排序:sort(),升序
- 比较:equals()
- 查找元素:binarySearch()
OOP
继承
extends的意思是"扩展",子类是父类的扩展
JAVA中只有单继承,无多继承!!!
Object类
通过ctrl+H看到类的继承关系
发现所有类都继承一Object类,该类提供了一些基础方法。
Super
调用父类的值和方法,与this对应
private属性的值和方法super无法访问
super():父类构造器,必须放在子类构造器的第一行
super和this不能同时调用构造方法
方法重写
- 静态方法
重写和静态方法没有关系,只和非静态方法有关系
public class A extends B{
public static void test()
{
System.out.println("A=>test()");
}
}
public class B{
public static void test()
{
System.out.println("B=>test()");
}
}
//方法的调用只和定义的数据类型有关
A a = new A();
a.test();//A=>test
//父类引用指向子类
B b = new A();
b.test();//B=>test
- 非静态方法
public class A extends B{
@Override //注解:有功能的注释!
public void test()
{
System.out.println("A=>test()");
}
}
public class B{
public void test()
{
System.out.println("B=>test()");
}
}
A a = new A();
a.test();//A=>test
//子类重写了父类的方法
B b = new A();
b.test();//A=>test
- 注意点
- 方法名、参数列表必须相同
- 修饰符:范围可以扩大,不能缩小 public>protected>default>private
- 抛出的异常:范围可以被缩小不能扩大
使用Alt+Insert:override也可使用快捷键进行重载
多态
同一方法根据发送对象的不同而采取多种不同的行为方式
一个对象的实际类型是确定的,但可以指向对象的引用类型有很多
/*
say() from both Student and Person
eat() only from Student
*/
// Student 能调用的方法是自己的或继承父类的
Student s1 = new Student();
// Person 可以指向子类,但不能调用Student独有的
Person s2 = new Student();
Object s3 = new Student();
s2.say();//equals ((Student) s2).say()=>Student say!
s1.eat();//correct
s2.eat();//wrong
- 注意事项
- 属性没有多态
- 多态源自继承,方法需要重写
- 父类引用指向子类对象,如果调用的方法在子类重载了则调用子类的方法。
- 动态编译,程序在运行时才知道执行哪个方法
- 不能多态的:
- static:属于类,不属于实例
- final:常量
- private方法
instanceof
boolean result = obj instanceof Class
其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。
注意:编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定。
- obj必须是引用类型,不能是基本类型
int i;
i instanceof Interger;//编译不通过
- obj为null
null算作基本类型和引用类型之外的一种类型,null是可以成为任意引用类型的特殊符号,如果obj为null返回false
null instanceof Object;//false
- obj为class的实例对象
Interger i = new Interger(1);
i instanceof Interger;//true
- obj为class类的直接或间接子类
true or false与引用是什么类型无关,而是与对象是什么类型有关
public class Man extends Person{}
Person p1 = new Person();
Person p2 = new Man();
Man m1 = new Man();
System.out.println(p1 instanceof Man);//false
System.out.println(p2 instanceof Man);//true
System.out.println(m1 instanceof Man);//true
- 编译不通过
编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定。
Person p1 = new Person();
System.out.println(p1 instanceof String);//编译报错
System.out.println(p1 instanceof List);//false
System.out.println(p1 instanceof List<Person>);//编译报错
按照我们上面的说法,这里就存在问题了,Person 的对象 p1 很明显不能转换为 String 对象,那么自然 Person 的对象 p1 instanceof String 不能通过编译,但为什么 p1 instanceof List 却能通过编译呢?而 instanceof List 又不能通过编译了?
instanceof伪代码:
boolean result;
if (obj == null) {
result = false;
} else {
try {
T temp = (T) obj; // checkcast
result = true;
} catch (ClassCastException e) {
result = false;
}
}
简单来说就是:**如果 obj 不为 null 并且 (T) obj 不抛 ClassCastException 异常则该表达式值为 true ,否则值为 false 。**因为(String)p1不能通过编译,而(List)p1可以,具体为什么之后再讨论。
static
静态变量被类中所有实例共享——在内存区里面只有一份,存储在专门的静态区中,可以直接通过类名访问,在类中调用静态属性或方法也不需要实例化对象就可以使用
静态导入包
//比如说只想导入Math.random这一个方法
//static不能少!
import static java.lang.Math.random;
random()//可以直接用,而非Math.random()
抽象类
//抽象类
public abstract class Action{
//抽象方法,只有方法名,没有实现
public abstract void doSomething();
//普通方法
public void doSpecificThing()
{
//实现
}
}
//子类必须实现所有的抽象方法,不然子类仍然是抽象方法!
public class A extends Action{
@Override
public abstract void doSomething()
{
//方法实现
}
}
抽象类不能实例化(new)
存在意义?提高代码开发效率,但是用的比较少,因为只能单继承,多用接口
接口
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范
关键字:interface
public interface TimeService {
void timer();
}
//每个接口都要有实现类
public interface UserService {
//属性都是public static final
int age = 99;
//方法都是public abstract
void run(String name);
}
//类 可以实现接口,并且可以实现多个接口以实现多继承
public class UserServiceImp implements TimeService,UserService{
@Override
public void timer() {
}
@Override
public void run(String name) {
}
}
作用:
- 定义一些方法的架构,让不同的人实现
- 接口不能被实例化,没有构造方法
- implements可以实现多个接口
- 必须要重写接口中的方法
异常
-
检查性异常
最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在的文件,一个异常就发生了,这些异常在编译时不能被简单地忽略
-
运行时异常
最可能被避免的异常,可以在编译时被忽略。
-
错误ERROR
不是异常,是脱离程序员控制的问题,经常在代码中被忽略。例如,栈溢出,在编译中检查不到。
Error和Exception的区别:Error通常是灾难性的致命的错误,程序无法控制和处理的,当出现这些异常,JVM选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
异常处理机制
- 抛出异常
- 捕获异常
快捷键ctrl Alt + T
// 可以用catch多次捕获,但是必须越细节异常在最上面
// 不过有没有捕获异常,都执行finally,经常用于执行一些IO或资源的关闭工作
try{//监控区域
System.out.println(a/b);
}catch (ArithmeticException e){//想要捕获的异常
System.out.println("程序出现异常,变量b不能为0");
}catch(Throwable e){
System.out.println("Throwable");
}finally{
System.out.println("finally");
}
//主动抛出异常,一般用在方法实现内部
try{
if (b==0)
throw new ArithmeticException();
}
//throws用在方法声明时
public void test(int a) throws ArithmeticException{
//表示这个方法可能会抛出这个异常,提醒调用者要进行处理
}
throws:用来声明一个方法可能产生的所有异常,不做任何处理而是将异常往上传,谁调用我我就抛给谁。
用在方法声明后面,跟的是异常类名
可以跟多个异常类名,用逗号隔开
表示抛出异常,由该方法的调用者来处理
throws表示出现异常的一种可能性,并不一定会发生这些异常
throw:则是用来抛出一个具体的异常类型。
用在方法体内,跟的是异常对象名
只能抛出一个异常对象名
表示抛出异常,由方法体内的语句处理
throw则是抛出了异常,执行throw则一定抛出了某种异常