Java学习–Day6
这是过年期间,零碎时间看的,所以是好几天的内容,基本JavaSE结束,有漏掉的,我再补充
Java方法详解(C++有接触,不多赘述)
可变参数
一个方法中只能指定一个可变参数,他必须是方法的最后一个参数,任何普通的参数必须在它之前声明。
public class Demo01 {
public static void main(String[] args) {
printMax(34,56,1,3,56,78,21,32);
printMax(new double[]{1,2,3});
}
//可变参数,也叫不定项参数
public static void printMax(double...numbers){
if(numbers.length==0){
System.out.println("No argument passed");
return;
}
double result = numbers[0];
//找最大
for(int i = 1;i < numbers.length;i++){
if(numbers[i] > result){
result = numbers[i];
}
}
System.out.println("The max value is" + result);
}
}
//结果为
The max value is78.0
The max value is3.0
数组
//静态初始化:创建+赋值
int[] a={1,2,3,4,5,6};
//动态初始化:包含数值的默认初始化
int[] b= new int[10];
b[0]=10;
面向对象
三大特征
- 封装
- 继承
- 多态
方法回顾
- 静态方法加关键字,在另一个类中可以用 类名**.**方法名 来调用方法
- 非静态方法,在另一个类中调用该方法时只能先实例化类的对象,然后通过对象来调用方法。
- 在静态方法中不能调用非静态方法,因为静态方法是和类一起加载的,而非静态方法是类实例化之后才存在的。
创建与初始化对象
使用类关键字new创建对象
class student{
//类中属性
String s_name;
int s_age;
//类中方法
public static void study(){
System.out.println(this.name+"在学习");
}
}
//创建学生类并初始化
Student xiaoming=new Student();
//初始化
xiaoming.s_name="小明";
xiaoming.s_age=12;
//此处若不初始化,则在用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认初始化,以及对类的构造器(下面细讲)的调用。
构造器
要求:
- 与类名相同,public修饰
- 无返回值
作用:
- 可以在new对象时,如果定义有参构造,一定要有无参构造(可以空着,但不能没有。)
- 可以用来初始化对象的值
快捷键:alt+insert添加构造器
class Person{
String name;
//无参构造器
public Person(){
}
//有参构造器
public Person(String name){
}
}
封装
程序设计要求:高内聚,低耦合
class Student{
//私有属性,不能通过 对象名.属性 来设置或获取属性值
//而应该调用Get与Set方法获取或设置
//快捷键:alt+insert
/*
*1.提高程序的安全性,保护数据
*2.隐藏代码的实现细节
*3.统一接口
*4.系统可维护性增加了
*/
private String name;
private int id;
private char sex;
public Student(){
}
public Student(String name){
}
public void setName(String name) {
this.name = name;
}
public void setId(int id) {
this.id = id;
}
public void setSex(char sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public char getSex() {
return sex;
}
}
继承
- 关键字extends
- Java中只有单继承,没有多继承,一个儿子只能有一个爸爸,但是一个爸爸可以有多个儿子。(在类中快捷键ctrl+h可查看继承的结构树)
- super关键字
package Base_Grammer;
//在java中,所有类都默认直接或间接继承Object类
public class Person {
private int money=10_000_000;
public void say(){
System.out.println("yoyo~");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
//super的用法
protected String identity = "I am father";
public void print(){
System.out.println("Person");
}
}
package Base_Grammer;
//子类继承父类,会继承父类所有public修饰的属性和方法
public class Student extends Person {
private String identity="I am student";
public void sayIdentity(String identity){
System.out.println(identity);//I am student
System.out.println(this.identity);//I am student
//通过super来调用父类的属性,同时也可以用这种方法来调用父类的方法,但私有方法,super也不能调用
System.out.println(super.identity);//I am father
}
public void print(){
System.out.println("Student");
}
//用super调用父类方法
public void test2(){
print();//Student
this.print();//Student
super.print();//Person
}
}
- 构造器的执行
此处父类必须要有无参的构造器(即使父类有有参构造器),如果没有子类的构造器会报错,这也就是为什么一个类一定要有无参构造器的原因。
package Base_Grammer;
//在java中,所有类都默认直接或间接继承Object类
public class Person {
public Person() {
System.out.println("Person的无参构造方法!");
}
}
package Base_Grammer;
//子类继承父类,会继承父类所有public修饰的属性和方法
public class Student extends Person {
public Student() {
//这一行为隐藏代码:调用了父类的无参构造器
super();//调用父类构造器,必须要在子类构造器的第一行
System.out.println("Student的无参构造方法!");
}
}
package Base_Grammer;
public class Test {
public static void main(String[] args) {
Student student = new Student();
//此时newStudent类对象时会打印两行结果
//Person的无参构造方法!
//Student的无参构造方法!
}
}
-
方法的重写
有继承关系,子类重写父类的方法!
先来看带static修饰的方法重写
package Base_Grammer; //A继承B类 public class A extends B { public static void test(){ System.out.println("A=>test()"); } } package Base_Grammer; public class B { public static void test(){ System.out.println("B=>test()"); } } package Base_Grammer; public class Test { public static void main(String[] args) { //现在看来方法的执行与定义的对象类型有关 A a = new A(); a.test();//A=>test() //父类的引用指向子类 B b = new A(); b.test();//B=>test() } }
去掉static关键字,用ctrl+o的快捷键重写父类方法
package Base_Grammer; public class A extends B { @Override//重写的功能注释 public void test() { System.out.println("A=>test()"); } } package Base_Grammer; public class B { public void test(){ System.out.println("B=>test()"); } } package Base_Grammer; public class Test { public static void main(String[] args) { A a = new A(); a.test();//A=>test() //父类的引用指向子类 B b = new A();//子类重写了父类方法 b.test();//A=>test() //因此只有非静态方法才能被重写 } }
总结
多态
//举几个例子来说好了
//一个对象的实际类型是确定的
//如new Student(),new Person()...
//但可以指向的引用类型就不一定了,如父类的引用指向了子类
//1.子类可以调用自己独有的和继承父类的方法
Student student = new Student();
//2.父类的引用虽然可以指向子类,但父类只能调用自己的方法(调子类的方法也不是不行,类型强转一下),并且,一旦方法被从写,这样定义的父类引用会执行子类重写后的方法,见总结上边的例子
Person person = new Student();
Object object = new Student();
类型转换
关键字:instanceof
x instanceof y来表明x与y是否有继承关系
- 父类转子类是要强制转换
- 子类转父类,可能丢失自己的一些方法
static关键字详解
-
静态变量可以通过类名来访问
-
静态方法可以通过类名来执行
-
静态方法只可以调用静态方法
-
静态代码块:类加载执行一次,且只执行一次,可以用来赋初始值
static{ //静态代码块 }
-
静态导入包
import static java.lang.Math.random; //这样可以直接用random()函数,不用加Math. 但一般没有这么做的
抽象类
关键字:abstract
package Base_Grammer;
//1.抽象类不能new,要考子类去实现它
//2.抽象类中可以有普通方法,但是抽象方法只能在抽象类中
//3.缺点就是,类只能单继承,一个儿子只能有一个爸爸,但接口可以多继承
public abstract class Action {
//抽象类中的抽象方法,只有方法名字,没有方法的实现
public abstract void run();
}
package Base_Grammer;
public class A extends Action {
//子类必须要重写父类抽象方法
@Override
public void run() {
}
}
【思考】抽象类含有构造器吗?
答:抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已。在继承了抽象类的子类中通过super()或super(参数列表)调用抽象类中的构造方法。
接口
关键字:interface,implements
- 实现了接口的类必须实现接口中的方法
- 接口中的方法默认是 public abstract的
- 接口中的常量是public static final类型的,但我们一般不定义常量
- 接口可以多继承:implements关键字
内部类
-
成员内部类
package Base_Grammer; public class Outer { private int id; public void out(){ System.out.println("这是外部类的方法"); } public class Inner{ public void in(){ System.out.println("这是内部类的方法"); } //内部类还可以获得外部类的私有属性 public void getID(){ System.out.println(id); } } } package Base_Grammer; public class Test { public static void main(String[] args) { Outer outer = new Outer(); //通过这个外部类来实例化内部类 Outer.Inner inner = outer.new Inner(); inner.in(); inner.getID(); } }
-
静态内部类
将上边的Inner类加上static修饰,这样会导致内部类无法获得外部类的私有属性
package Base_Grammer; public class Outer { private int id; public void out(){ System.out.println("这是外部类的方法"); } public static class Inner{ public void in(){ System.out.println("这是内部类的方法"); } //内部类还可以获得外部类的私有属性 public void getID(){ System.out.println(id);//这里会报错滴 } } }
-
局部内部类
package Base_Grammer; public class Outer { //局部内部类 public void method(){ class inner{ public void in(){ } } } }
-
匿名内部类
package Base_Grammer; public class Test { public static void main(String[] args) { //没有名字的初始化类,不用将实例保存到变量中 new Apple().eat(); new Userservice(){ @Override public void hello() { } }; } } class Apple{ public void eat(){ System.out.println("eat"); } } interface Userservice{ void hello(); }
异常机制
Java分为两类,错误Error和异常Exception,异常可以抛出处理
快捷键:选中要抛出异常的部分,然后ctrl+alt+t
1.try,catch,finally
package Base_Grammer;
public class Test {
public static void main(String[] args) {
int a = 1;
int b =0;
try {//try监控区域
System.out.println(a/b);
}catch (ArithmeticException e){//catch捕获异常,参数为想要捕获的异常类型
System.out.println("变量b不能为零");
}finally {//处理善后工作
System.out.println("finally");
}
//finally可以不要,但一般要写,比如关闭一些资源流的时候,如I/O流
//假设要捕获多个异常,一定要从小到大捕获,不然会报错
try{
System.out.println(a/b);
}catch (Error e){
System.out.println("error");
}catch (Exception e){
System.out.println("exception");
}catch(Throwable t){
System.out.println("throwable");
}finally {//处理善后工作
System.out.println("finally");
}
}
}
2.throw,throws
package Base_Grammer;
public class Test {
public static void main(String[] args) {
try {
new Test().test(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();//这里是打印错误栈信息
}
}
//假设这方法中,处理不了这个异常,方法上抛出异常
public void test(int a,int b) throws ArithmeticException {
if (b == 0) {
//知道这里必定出错,主动抛出异常,一帮在方法中使用
throw new ArithmeticException();
}
System.out.println(a / b);
}
}
3.自定义异常
只要继承Exception类就行
package Base_Grammer;
public class MyException extends Exception {
//假设数字大于10就产生异常
private int detail;
public MyException(int a){
this.detail = a;
}
//为打印信息,添加个toString方法
@Override
public String toString() {
return "MyException{" +
"detail" + detail +
'}';
}
}
package Base_Grammer;
public class Test {
static void test(int a) throws MyException {
System.out.println("传递的参数为:"+a);
if(a>10){
throw new MyException(a);//抛出
}
System.out.println("ok");
}
public static void main(String[] args) {
try {
test(11);
} catch (MyException e) {
//这里还可以增加一些处理异常的代码块
System.out.println("MyException===>"+e);
}
}
}