一.final
final修饰局部变量:
基本数据类型:如果局部变量是一个基本数据类型,那么被final修饰,基本数据类型的变量的值不能改变!
引用数据类型:如果用final修饰引用类型的变量,那么它不能在重写分配堆内存空间,但是可以改变成员变量的值.
相关代码:
class Student{
int age;
}
public class FinalTest {
public static void main(String[] args) {
int num=10;
num=20;
System.out.println(num);
System.out.println("-----------");
final int num2=30;
// 基本数据变量的值不能改变
// num2=40;
System.out.println(num2);
System.out.println("-----------");
Student s=new Student();
s.age=10;
System.out.println(s.age);
System.out.println("-----------");
final Student ss=new Student();
ss.age=20;
System.out.println(ss.age);
ss.age=30;
System.out.println(ss.age);
// 不能重新分配堆内存空间
// ss=new Student();
}
}
结果为:20
-----------
30
-----------
10
-----------
20
30
二.多态
1.多态:一个事物在不同时刻体现出的不同状态.
2多态的三个前提:
1>必须有继承关系(没继承谈不上多态);
2>必须有方法重写;
3>有父类引用指向子类对象:向上转型
Fu zi = new zi();
三个条件缺一不可.
3,多态的成员访问特点:
成员变量:
编译看左,执行看左;
成员方法(飞静态成员方法):
编译看左,执行看右;由于存在方法重写,所以最终运行的是子类成员方法;
静态成员方法:
编译看左,运行看左;
构造方法:
对象进行初始化,由于是一种继承关系,所以还是分层初始化!
相关代码:
class Fu{
public int num=10;
public void show(){
System.out.println("show Fu");
}
public static void function(){
System.out.println("function Fu");
}
}
class Zi extends Fu{
int num=20;
public void show(){
System.out.println("show Zi");
}
public static void function(){
System.out.println("function Zi");
}
}
// 测试类
public class DuoTaiDemo {
public static void main(String[] args) {
// 创建对象(多态形式),由父类引用转向子类对象:向上转型
Fu f=new Zi();
// 访问成员变量
System.out.println(f.num);
// 调用成员方法:show
f.show();
// 调用静态方法:function
f.function();
}
}
结果为:10
show Zi
function Fu
多态的好处(特点):
1)提高代码的维护性(由继承保证)
2)提高代码的扩展性(由多态保证)
Java的开发原则:低耦合,高内聚.
多态的弊端:
不能访问子类的特有功能:异常:OOM异常:严重:OutOfMemory:内存溢出!
解决方案:
* 1)创建子类的具体对象,来访问自己的特有功能;虽然可以解决多态的弊端,但是从内存角度考虑,需要创建子类对象,那么必须在堆内存开辟空间,
* 耗费内存,浪费空间!
* 2)既然多态的第三个前提条件:父类引用指向子类对象,那么可不可以将子类的引用指向父类对象呢?
* 可以的:向下转型:将父类的引用强制转换为子类的引用:前提必须有父类的引用存在;
* 向下转型必须依赖于向上转型!
相关代码:
class Animal{
public void show(){
System.out.println("show Animal");
}
}
class Cat extends Animal{
public void show(){
System.out.println("show Cat");
}
//特有功能
public void eat(){
System.out.println("show eat");
}
}
// 测试类
public class DuoTaiDemo {
public static void main(String[] args) {
//由父类引用指向子类对象
Animal a=new Cat();
a.show();
//不能调用子类特有功能
// a.eat();
//创建子具体对象
/*Cat c=new Cat();
c.show();
c.eat();*/
//父类的引用强制转化为子类的引用:向下转换
Cat c=(Cat) a;
c.eat();
}
}
结果为:show Cat
show eat
一般情况下:向下转型使用不当会造成一个异常:Throwable:
error:严重问题
Exception:
编译时期异常:
运行时期异常:RuntimeException
运行时期异常:
ClassCastException:类转换异常:org.westos_02_多态.Cat4 cannot be cast to org.westos_02_多态.Dog4
相关部分代码:
//测试类:
public class DuoTaiDemo5 {
public static void main(String[] args) {
//内存是狗
Animal4 a = new Dog4() ;
//向下转型:还原成狗
Dog4 d = (Dog4)a ;
//内存是猫
a = new Cat4() ;
//还原成猫
Cat4 c = (Cat4) a ;
//编译通过了
Dog4 dd = (Dog4)a ; //不能将内存猫转换为狗
}
}
相关图解:
三.抽象类
抽象类概念:一个类中有抽象方法,那么这个类一定定义为抽象类!
当然一个抽象类可以抽象,也可以有抽象的(判断题!).
抽象类不能实例化:
抽象类想要实例化必须通过抽象类多态形式:父类的引用指向子类对象.
因此子类不能是抽象类!
抽象类多态:
强制子类重写父类所有的抽象方法,可以提高代码的维护性(继承关系保证!).
抽象类的方法特点:
成员方法:
可以使变量也可以是自定义常量!
构造方法:
抽象类有构造方法,当然可有参可无参构造!
成员方法:
可有抽象方法和非抽象方法!
非抽象方法:由继承提高代码的复用性.
相关代码:
结果为:Animalabstract class Animal{ //成员变量 private String name; private int age; //无参构造 public Animal(){ } //有参构造 public Animal(String name,int age){ this.name=name; this.age=age; } //抽象方法 public abstract void show(); // 具体方法 public void print(){ System.out.println("Animal"); } } class Cat extends Animal{ @Override public void show() { System.out.println("show Cat"); } } //测试类 public class AbstractDemo { public static void main(String[] args){ //父类引用指向子类对象 Animal a=new Cat();//Animal抽象类,需要抽象多态形式 //访问抽象方法 a.print(); a.show(); } }
show Cat
注意:一个类如果没有抽象类,也可以定义为抽象类!
private,final,static不能与abstract共同使用!
四.接口
接口的概念:体现一种扩展功能.
接口的表示:interface 接口名
接口里只能有抽象方法,没有构造方法.
接口的特点:不能被实例化.因此只能通过接口的子类实现,子类只能是非抽象类.
成员变量:只能是常量;默认符号为:public static final
成员方法:接口里的成员方法默认修饰符:public abstract;
接口的子实现类与接口的关系:implments
格式:class 子实现类 implments 接口名.
相关代码:
interface Inter{ //成员变量 public static final int num=10; //成员方法 public abstract void show(); } class InterImp implements Inter{ @Override public void show() { System.out.println(num); } public void say(){ System.out.println("I love you"); } } public class InterfaceDemo { public static void main(String[] args) { //创建对象:使用多态 Inter i=new InterImp(); i.show(); InterImp ii=(InterImp) i;//向下转换 ii.say(); } }
结果为:10
类与类的关系:继承关系:extends,Java中只支持单继承,不支持多继承,但可以多层继承!I love you
类与接口的关系:实现关系:implements,一个类在继承另一个类的时候,可以实现多个接口!
接口与接口的关系:继承关系:extends,可以支持单继承,也可以多继承!
格式:class 子实现类 extends Object implements 接口1,接口2...
五.APIAPI的使用:打开API:
显示---->输入你查找的类
索引---->搜索
找到某一个类:
对该类的描述
看类结构:
看该类是否有字段(变量),构造方法(如何创建该类对象),方法(类的成员方法)
出现该类的版本号:
Scanner java.util.Scanner;
JDK5.0以后的新特性:自动拆装箱(int--->Integer,char--->Character),静态导入(导入的方法级别),可变参数,增强for循环(集合),枚举
JDK7.0也有新特性(匿名内部类:局部内部类访问局部变量特性:局部变量必须被final讲)制作API文档的相关代码:
/** * 该类是针对数组操作的一个工具类,里面有一些对数组操作的功能 * @author Apple * @version V1.0 * */ public class ArrayTool { //无参构造私有,目的为了不让外界其对象 private ArrayTool(){ } /** * 该方法是针对数组的遍历的方法,遍历的元素[元素1, 元素2, 元素, ....] * @param arr :需要被遍历的数组 * */ public static void printArray(int[] arr){ System.out.print("["); for(int x = 0 ; x < arr.length ; x ++){ if(x==arr.length-1){ System.out.println(arr[x]+"]"); }else{ System.out.print(arr[x]+", "); } } } /** * 该方法是针对数组获取最大值的方法 * @param arr :需要被遍历的 数组,可以获取每一个元素 * @return 返回的就是数组中最大值 * * */ public static int getMax(int[] arr){ //定义参照物 int max = arr[0] ; //遍历其他索引 for(int x = 1 ; x < arr.length ;x ++){ //判断 if(arr[x]>max){ max = arr[x] ; } } return max ; } /** * 该方法是查询数组中的元素在数组中第一次出现的索引 * @param arr : 需要查询的数组 * @param value:需要被查找的远古时 * @return 如果查到了当前索引对应的元素,那么就直接返回当前索引,如果查不到,则返回-1 * */ public static int getIndex(int[] arr,int value){ //假设法 //定义一个索引:假设查不到 int index = -1 ; //遍历数组 for(int x = 0 ; x < arr.length ; x ++){ //判断:如果刚好查到的x索引对应的元素和value相等,那么返回该索引 if(arr[x]==value){ //表查到了 //给索引遍历重新赋值 index = x ; break ; } } return index ; } }
六.内部类/** * 1)需要定义一个类工具类:ArrayTool数组工具类:给该类写上文档注释(每一个静态方法都需要使用文档注释) * 2)需要将该类的无参私有化,目的是为了让外界创建对象 * 3)ArrayTool中的成员方法全部用static修饰 * 4)测试完毕 * 5)如何制作API文档 * 针对ArrayTool来制作 * 打开dos---->javadoc -d 目标名(文件名) -author -version ArrayTool.java * */ public class ArrayDemo { public static void main(String[] args) { //定义一个数组,静态初始化 int[] arr = {24,69,80,57,13} ; //遍历数组 ArrayTool.printArray(arr) ; //获取数组中的最大值 int result = ArrayTool.getMax(arr) ; System.out.println("result:"+result); //查询577元素 int index = ArrayTool.getIndex(arr, 577) ; System.out.println("index:"+index); int index2 = ArrayTool.getIndex(arr, 57) ; System.out.println("index2:"+index2); } }
内部类概念:在一个类中定义另一个类.
内部类是直接可以访问外部类的成员,包括私有.
外部类想访问内部类,必须创建内部类的对象访问该内部类的成员.
内部类的分类:
成员内部类:在外部类的成员位置.
局部内部类:在外部类的局部位置定义这个类.
访问成员内部类:外部类名.内部类名 对象名=外部对象.内部对象
要访问外部类的成员变量:匿名对象 :new 外部类名().成员变量
成员内部类的修饰符:
private :为了保证数的安全性.直接创建外部类对象.
static修饰:为了方便调用
如果成员内部类被static修饰,那么外部类必须要被static修饰
静态成员内部类访问该类中的方法:
格式:外部类名.内部类名 对象名=new 外部类名.内部类名();
相关代码:
结论:对于静态内部类,要想访问外部类成员变量,该成员变量都要被static修饰.class Outer{ //成员变量 public int num=10; public static int num1=20; //成员内部类(非静态) class Inter1{ public void show(){ System.out.println(num); System.out.println(num1); } } //成员内部类(静态) public static class Inter2{ //非静态方法 public void show(){ // System.out.println(num); System.out.println(num1); } public static void show1(){ // System.out.println(num); System.out.println(num1); } } } public class InnerDemo { public static void main(String[] args) { Outer.Inter1 oi1=new Outer().new Inter1(); oi1.show(); System.out.println("------------"); Outer.Inter2 oi2=new Outer.Inter2(); oi2.show(); oi2.show1();//静态方法 System.out.println("------------"); //另一种访问show1 Outer.Inter2.show1(); } }
局部内部类:
对于局部内部类的访问:创建外部类对象,用外部类对象调用外部类成员方法.局部内部类访问局部变量时,局部变量需要被final修饰,由于局部变量是随着方法调用生成的,随着方法的调用完毕消失,而现在局部位置有一个局部内部类要在自己的成员方法
位置调用局部变量,则把局部变量变成一个常量.
相关代码:
匿名内部类:class Outer{ //成员变量 public int num=10; //成员方法 public void method(){ //局部变量 final int num1=20; //局部位置 class Inner{ //局部内部类成员方法 public void show(){ System.out.println(num); System.out.println(num1); } } Inner i=new Inner(); i.show(); } } public class InnerDemo { public static void main(String[] args) { //对于局部内部类访问时调用外部类成员方法,因此创建外部类对象,调用该方法. Outer o=new Outer(); o.method(); } }
相关代码:
面试题:interface Inter1{ public abstract void study() ; } class StudentDemo{ public void method(Inter1 i){//形式参数是一个接口 i.study() ; } } public class OuterTest { public static void main(String[] args) { //需求:调用StudentDemo中的method()方法 StudentDemo sd = new StudentDemo() ; sd.method(new Inter1(){ @Override public void study() { System.out.println("好好学习,天天向上..."); } }) ; } }
按照要求,补齐代码
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
代码:
分析:当前method()能直接被Outer调用,则该方法是静态的;Outer.method().show()->Outer.method()返回的是一个对象,所以用对象调用show()方法.另外重写show方法.interface Inter1{ public abstract void show(); } class Outer1{ public static Inter1 method(){//返回值是一个接口 return new Inter1(){ @Override public void show() { System.out.println("HelloWorld"); } }; } } public class OuterDemo { public static void main(String[] args) { Outer1.method().show(); } }
七.形式参数和返回值.
形式参数:
基本类型:要什么数据类型,在实际传参的时候就传什么数据类型.
引用类型:
具体类:需要创建具体对象.
抽象类:需要自定义一个抽象类的子类,抽象类多态进行实例化.
接口:需要自定义一个接口的子类,接口多态进行实例化.
相关代码:
class person{ public void show(){ System.out.println("I love you"); } } class personDemo{ public void method(person p){//形式参数引用具体类 p.show(); } public void method1(person1 p1){//形式参数引用抽象类 p1.show(); } public void method2(person2 p2){//形式参数引用接口 p2.show(); } } abstract class person1{ public abstract void show(); } class person1Demo extends person1{ @Override public void show() { System.out.println("you love me"); } } interface person2{ public abstract void show(); } class person2Demo implements person2{ @Override public void show() { System.out.println("那就结婚吧!"); } } public class PersonDemo { public static void main(String[] args) { personDemo pd=new personDemo();//创建对象,调用method() person p=new person(); pd.method(p);//形参是具体类 System.out.println("----------"); person1 p1=new person1Demo(); pd.method1(p1);//形参是抽象类 System.out.println("----------"); person2 p2=new person2Demo();//形参是接口 pd.method2(p2); } }
返回值类型:
基本类型
应用类型:
具体类:直接返回该类对象.(通常使用匿名对象)
抽象类:返回该抽象类的子对象.
接口:返回该接口的子对象.
相关代码:
class person{ public void show(){ System.out.println("I love you"); } } class personDemo{ public person method(){//返回值引用具体类 return new person(); } public person1 method1(){//返回值引用抽象类 return new person1Demo(); } public person2 method2(){ return new person2Demo();//返回值引用接口 } } abstract class person1{ public abstract void show(); } class person1Demo extends person1{ @Override public void show() { System.out.println("you love me"); } } interface person2{ public abstract void show(); } class person2Demo implements person2{ @Override public void show() { System.out.println("那就结婚吧!"); } } public class PersonDemo { public static void main(String[] args) { personDemo pd=new personDemo();//创建对象,调用method() person p=pd.method(); p.show();//返回值是具体类 System.out.println("----------"); person1 p1=pd.method1(); p1.show();//返回值是抽象类 System.out.println("----------"); person2 p2=pd.method2(); p2.show();//返回值是接口 //链式编程 person2 p3=new personDemo().method2(); p3.show(); } }