方法的形式参数
在idea里面常常用的快捷键:
alt+enter--->自动提示补全代码, 类似eclipse有一个"alt+/"
ctrl+shift+/ -->将多行的代码 加入多行注释 (在此取消多行 ctrl+shift+/)
ctrl+/ --->添加单行注释
形式参数问题:
一个方法的形式参数是基本类型: 形式参数的改变不会影响实际参数! (需要什么类型,传递具体数据类型的对应的数据值即可!)
一个方法形式参数是引用数据类型:除过String类型,形式参数的改变会直接影响实际参数!
如果一个方法的形式参数是一一个引用类型 :类
调用方法的时候,实际参数需要是当前这个类的对象!(空间地址值)
import java.util.Scanner;
//定义一个Demo类
class Demo{
//成员方法
public int sum(int a,int b){ //形式参数是基本数据类型
return a + b ;
}
}
//定义一个学生类
class Student{
//成员方法
public void study(){
System.out.println("Good Good Study, Day Day Up!!!");
}
}
//定义一个类StudentDemo类
class StudentDemo{
//成员方法
public void method(Student student){ //方法的形式参数是一个引用类型:Student类 ,实际调用,需要去创建Student类的对象!
student.study() ;
}
/*public void change(int[] arr){ //数组*/ //数组引用类型:调用这个方法的时候 需要真实的数组 int[] arr = {xxx} ;
/* for(int x = 0 ; x < arr.length ; x++){*/
/* if(arr[x] % 2==0){*/
/* arr[x] *=2 ;*/
/* }*/
/* }*/
/*}*/
}
//测试类
public class ArgsDemo {
public static void main(String[] args) {
//1)访问Demo类中的sum方法?
//创建Demo类的对象
Demo d = new Demo() ;
int result = d.sum(10, 20) ; //传递具体的数据值即可
System.out.println(result);
System.out.println("---------------------------------------------") ;
//2)要访问Student类的study方法?
Student s = new Student() ; //创建学生类对象
s.study();
System.out.println("--------------------方法形式参数是一个引用类型:类的情况-----------------------------") ;
//3)要访问StudentDemo类中method方法?
// 创建 StudentDemo 这个类的对象
StudentDemo sd = new StudentDemo() ;
//调用method方法
//需要创建具体的学生对象
Student student = new Student() ;
sd.method(student); //方法的形式参数:一个Student类,实际参数需要具体的学生对象
}
}
代码块
/**
*什么是Java中的代码块?
*
* Java中的代码块是一个{}包裹起来的内容!
* 分类:
* 局部代码块--->方法定义中 作用:限定局部变量的生命周期
* 构造代码块--->类的成员位置定义的{}
* 作用:在执行构造方法之前,如果存在构造代码块,先执行构造代码块,
* 然后在执行构造方法 ,就是给数据进行初始化的!
* 静态代码块--->类的成员位置定义的
* static{
*
* }
* 特点:跟类相关,类一加载,先执行,而且只执行一次(因为类就加载一次)
* 优先级最大
*
*
*
* 优先级:
* 静态代码块 > 构造代码块 > 构造方法!
*
*/
import com.sun.xml.internal.ws.addressing.WsaActionUtil;
//定义一个Code类
class Code {
//静态代码块
static{
int x = 1000 ;
System.out.println(x) ;
}
public Code() {
System.out.println("code的无参构造方法");
}
//构造代码块
{
int x = 100 ;
System.out.println(x) ;
}
//构造代码块
{
int y = 200;
System.out.println(y);
}
//有参构造
public Code(String name){
System.out.println("code"+name) ;
}
static{
int y = 2000 ;
System.out.println(y) ;
}
}
//测试类
public class CodeDemo {
public static void main(String[] args) {
//方法中 {},局部代码块
/* {
int x = 100 ;
System.out.println(x) ;
}*/
//System.out.println(x);
// System.out.println("------------------------------") ;
//创建Code类的对象---无参构造方法创建
Code code = new Code() ;
System.out.println("------------------") ;
Code code2 = new Code("helloworld") ;
}
}
继承
/**
* 继承的概念:
* 将多个类的共性内容抽取到一个独立的类中,这个独立的类和这多个类产生一种关系 "继承"
*
* 继承的格式:
* class 父类名{}
* class 子类名 extends 父类名{}
*
* 继承的好处:
* 1)可以提高代码的复用性
* 2)可以增强代码的后期维护
* 3)类与的类关系:继承关系 是多态的前提条件!
*
*
* 使用"继承"的时机:什么时候使用继承?
*
* class A{
* public void show(){}
* public void show2(){}
* }
* class B{
* //public void show(){}
* public void show3(){}
* }
*
* ---->优化 class B extends A{}
* 不能为了使用部分功能就使用继承!
* 使用继承的前提条件:
* 如果一个类A是类B一种,或者是类B是类A的一种,才能使用继承,继承的核心思想体现出一种"is a"的关系
* 举例:
* 水果:
* 橘子
* 苹果
* 西瓜..
* 人:
* 工人
* 学生
* 军人
* 老师....
*
* 实际开发中:
* 所有的开发原则都必须遵循 "低耦合,高内聚"
*
* 耦合:类和类的关系越少越好,耦合性只能降低,不能避免!
* 内聚:解决某件事情(功能)的执行力!(一个类能够完成的尽量一个类完成,不能产生过多关系!)
*
*/
//没有使用继承之前
//学生类
/*class Student{
//学生要学习
public void study(){
System.out.println("任何人都要学习");
}
//学累了就要休息
public void sleep(){
System.out.println("学习困了就需要休息");
}
}
//老师类
class Teacher{
//学习
//学生要学习
public void study(){
System.out.println("任何人都要学习");
}
//学累了就要休息
public void sleep(){
System.out.println("学习困了就需要休息");
}
}*/
//将共性内容抽取到独立类中
//使用继承
class Person{ //人
//学生要学习
public void study(){
System.out.println("任何人都要学习");
}
//学累了就要休息
public void sleep(){
System.out.println("学习困了就需要休息");
}
}
//定义学生类
class Student extends Person{}
//定义老师类
class Teacher extends Person{}
//测试类
public class ExcetendsDemo {
public static void main(String[] args) {
//测试
//创建学生类对象
Student s = new Student() ;
s.study();
s.sleep();
System.out.println("--------------------------------") ;
//创建老师类对象
Teacher t = new Teacher() ;
t.study() ;
t.sleep() ;
}
}
继承的特点
/**
* 继承的特点:
* 1)在Java语言中,类与类的关系,只支持单继承 (类是Java中最基本的单元)
* 举例:
* class Fu{}
* class Fu2{}
* class Zi extends Fu,Fu2{} 这种写法错误格式
* 2)类与类之间虽然不支持多继承,但是可以多层继承!
*
*/
//爷爷
class GrandFather{ //在Java中最顶层的类:Object(所有类的父类) ,可以省略不写!
public void method(){
System.out.println("我是爷爷");
}
}
//父类
class Father extends GrandFather{
public void show(){
System.out.println("我是老子");
}
}
/*class Mother{
}*/
//子类
//class Son extends Father,Mother{} //多继承(类的关系,Java不支持!)
class Son extends Father{
public void function(){
System.out.println("function Son");
}
}
//测试类
public class ExtendsDemo2 {
public static void main(String[] args) {
//创建具体的子类
Son s = new Son() ;
s.function(); //访问自己的功能
s.show(); //继承 父类的功能
s.method(); //间接继承了他爷爷的功能
}
}
注意事项
package com.qf.extends_05;
/**
* 继承的注意事项:
* 1)子类继承父类,是可以继承父类所有的东西,只不过父类的私有的属性以及方法只能在本类中访问
*子类是不能直接访问到的,但是可以间接的通过公共方法来访问!
* 2)子类继承父类,不能继承父类的构造方法(无参/有参构造),可以通过 "super"来访问父类的构造方法!
*
*/
//父类
class Fu{
//私有的
private int num = 100 ;
//非私有的
public int num2 = 200 ;
//定义一个成员方法
public void show(){
System.out.println(num) ;
System.out.println(num2) ;
}
//私有方法
private void method(){
System.out.println("method Fu...");
}
//非私有
public void mySelfMethod(){
method(); //调用了私有方法
}
}
//子类
class Zi extends Fu{
//子类的成员方法
public void function(){
System.out.println(num2);
// System.out.println(num);
}
}
//测试类
public class ExtendsDemo3 {
public static void main(String[] args) {
//创建Zi类对象
Zi z = new Zi() ;
z.function(); //使用自己的成员方法
z.show(); //继承父类的, 父类的show方法里面有一个父类私有属性
//z.method();//父类的私有方法,不能直接访问
System.out.println("------------------------");
z.mySelfMethod();
}
}
测试
/**
* 面试题
*看程序,补全代码,分别在控制台打印-- 30 20 10
* super:代表的是父类的空间标识(父类对象的地址值引用)
* this:代表本类对象的地址值引用
*/
class Fu2{
int num = 10 ;
}
class Zi2 extends Fu2{
int num = 20 ;
public void show(){
int num = 30;
//补全代码
System.out.println(num) ;
System.out.println(this.num); //访问的是本类的成员变量
System.out.println(super.num); //访问父类的成员变量
}
}
//测试类
public class ExtendsTest {
public static void main(String[] args) {
Zi2 z = new Zi2() ;
z.show();
}
}
测试
/**
* 看程序,写结果
* 考点:
* 代码块的优先级
* 静态代码块 > 构造代码块 > 构造方法
* 继承关系问题
* 子类的所有构造方法默认父类的无参构造方法,目的就是让父类初始化的,然后在子类初始化!
*/
class Person{
public Person(){
System.out.println("这是Person类的无参构造方法");
}
static{
System.out.println("Person的静态代码块");
}
{
System.out.println("Person的构造代码块");
}
}
//子类
class Student extends Person{
public Student(){
//super();
System.out.println("Student的无参构造方法");
}
public Student(String name){
System.out.println("Student的有参构造方法");
}
{
System.out.println("Student的构造代码块");
}
static{
System.out.println("Student的静态代码块");
}
}
public class ExtendsTest2 {
public static void main(String[] args) {
Student s = new Student() ;
Student s2 = new Student("高圆圆") ;
}
}
父类子类成员变量名称一致问题
/**
*
* 继承关系中成员问题:
* 一个类的成员:
* 成员变量
* 成员方法
* 构造方法
*
*
* 1)子类继承父类,子类中 成员变量如果父类中的成员变量名称不一致的情况:比较简单,分别访问即可!
* 2)子类继承父类,如果子类的成员变量名称和父类的成员变量名称一致,如何访问呢?
*
* a)先在子类的局部位置(子类的成员方法中定义变量:局部变量)找,如果存在,就使用
* b)如果子类的局部位置没有,然后才在子类的成员位置找,如果存在,就使用
* c)如果子类的成员位置没有,然后在父类的成员位置找,如果存在,就使用
* d)如果父类的成员位置也没有,说明当前没有这个变量,就访问报错!
*
* 一句话:就近原则!
*/
//父类
class Fu{
//父类的成员变量
int num = 20 ;
}
//定义一个子类
class Zi extends Fu{
//子类的成员变量
//int num2 = 30 ;
int num = 100 ;
//子类的成员方法
public void show(){
int num = 30 ; //局部变量
System.out.println(num) ;
//System.out.println(num2);
}
}
//测试类
public class ExtendsDemo4 {
public static void main(String[] args) {
//创建子类对象
Zi z = new Zi() ;
z.show();
}
}
访问父类方法
/**
* 继承关系中:
* 子类继承父类,子类如何访问父类的构造方法?
* 通过super关键字
*
* 1)子类继承父类,不能继承父类的构造方法,但是可以通过super访问,子类的所有构造方法默认访问父类的无参构造方法!
* 子类的构造方法的第一句话:都有super() ; 访问父类的无参构造方法
* 原因:
* 子类继承父类,可能用到父类的属性(成员变量)这些数据,必须让父类先初始化,然后子类才能初始化(构造方法,就是给数据初始化的)
* 这种过程----继承中 "分层初始化"
* 2)永远建议把父类的无参构造方法给出来,可能户导致子类的构造方法报错!
*
*/
//定义一个父类
class Fu3{
//假设:姓名,年龄,性别...属性(成员变量)
//父类给一个无参构造方法
public Fu3(){
System.out.println("这是Fu3的无参构造方法");
}
/*public Fu3(String name){
System.out.println("Fu3的有参构造方法,"+name);
}*/
}
//子类
class Zi3 extends Fu3{
//子类的无参构造方法
public Zi3(){
// super() ;//可以隐藏不写
System.out.println("Zi3的无参构造方法");
//super() ; 放在后面,可能初始化多次,jvm编译不让通过! 必须在第一句话
}
//子类的有参构造方法
public Zi3(String name){
//super() ;//可以隐藏不写
System.out.println("Zi3的有参构造方法,"+name);
}
}
//测试类
public class ExtendsDemo5 {
public static void main(String[] args) {
//通过子类的无参构造方法,创建子类对象
Zi3 z = new Zi3() ;
System.out.println("--------------------") ;
//通过子类的有参构造放,创建子类对象
Zi3 zz = new Zi3("hello") ;
}
}
继承注意事项
/**
* 继承关系中的构造方法的注意事项
*
* 子类继承父类,子类的所有构造方法第一句话都隐藏了默认 super() ;访问父类的无参构造方法,只存在父类的有参构造方法
* 那么,如果父类中并没有给出无参构造方法,子类会出现什么情况?如何解决?
*
* 子类的所有构造方法都会报错!默认都要访问父类无参构造方法(默认机制)
* 解决方案:
* 1)自己手动给出父类的无参构造方法(推荐)
* 2)不给出父类的无参构造方法,怎么解决?
* 让子类的所有构造方法都直接来访问父类的有参构造方法,只要父类初始化即可!
* 3)所有的子类的构造方法只要有一个让父类初始化即可!
* 在子类的无参构造方法中第一句话: this(xxx) ; 访问本类(子类)的有参构造方法
* 在通过子类的有参构造方法的第一句话:super(xxx) ;访问父类的有构造方法---->父类先初始化完毕完毕
*
*
* 实际开发中:(写继承代码的时候)
* 子类继承父类,子类的无参构造方法访问父类的无参!
* 子类的有参构造方法访问父类的有参!
*/
//定义一个父类
class Father{
//手动给出Father的无参
/* public Father(){
System.out.println("Father的无参构造方法");
}*/
//Facther的有参构造
public Father(int num){
System.out.println("Father的有参构造方法:"+num) ;
}
}
//定义一个子类
class Son extends Father{
//Son类的无参构造方法
public Son(){
super(100) ; //访问父类的有参构造方法
//this(100) ;//访问本类的有参构造方法
System.out.println("Son的无参构造方法");
}
//Son的有参构造方法
public Son(int num){
//super(20) ; //访问父类的有参构造方法
this() ;//访问本类无参构造方法
System.out.println("Son的有参构造方法:"+num);
}
}
//测试类
public class ExtendsDemo6 {
public static void main(String[] args) {
// Son s = new Son() ;
Son s = new Son(50) ;
}
}
举例
package com.qf.extends_07;
/**
* 动物类
* 属性:name,age,color---私有化
* setXXX(xx)/getXXX()
* 行为:eat(),sleep()
*/
public class Animal {
//属性--私有化
private String name ; //姓名
private int age ; //年龄
private String color ; //毛色
//无参构造方法
//alt+ins--->constructor--->select none
public Animal() {
}
//有参构造方法
//alt+ins--->constructor--->cltr+a--->回车
public Animal(String name, int age, String color) {//"哆啦A梦",5,"蓝色"
this.name = name;
this.age = age;
this.color = color;
}
//公共访问方法setXXX(xx)/getXXX()
//alt+ins--->getter and setter--->altr+a--->回车
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
//其他成员方法
public void eat(){
System.out.println("动物都需要吃饭") ;
}
public void sleep(){
System.out.println("动物累了就需要休息");
}
}
package com.qf.extends_07;
/**
* 猫狗案例---继承版
*
* 猫和狗--都有姓名,年龄,毛色
* 猫和狗---吃和睡的功能
*
* 现在使用面向对象的方式,加入继承,在AnimalTest测试猫和狗
* 分析:
* 猫类--描述 猫事物
* 属性:name,age,color---私有化
* setXXX(xx)/getXXX()
* 行为:eat(),sleep() , 特有功能:catchMouse()
* 狗类--描述 狗事物
* 属性 :name,age,color---私有化
* setXXX(xx)/getXXX()
* 行为:eat(),sleep(),特有功能:lookDoor()
*
* 将猫和狗的共性内容---抽取到一个独立的类中 "动物类"---描述动物的
* 属性:name,age,color---私有化
* setXXX(xx)/getXXX()
* 行为:eat(),sleep()
*/
//测试类
public class AnimalTest {
public static void main(String[] args) {
//创建一只狗
//无参构造方法+ setXXX(xx)/getXXX()
Dog d = new Dog() ;
d.setName("拉布拉多") ;
d.setAge(5) ;
d.setColor("棕色") ;
System.out.println(d.getName()+"---"+d.getAge()+"---"+d.getColor());
d.eat();
d.sleep();
d.lookDoor();
System.out.println("--------------------------------") ;
//方式2:有参构造方法直接赋值+getXXX()
Dog d2 = new Dog("二哈",3,"白色") ;
System.out.println(d2.getName()+"---"+d2.getAge()+"---"+d2.getColor());
d2.eat();
d2.sleep();
d2.lookDoor();
}
}
package com.qf.extends_07;
/**
* 猫类
*/
public class Cat extends Animal{
//猫的无参构造方法
/* public Cat(){ //Cat cat = new Cat() ;
//super();
}*/
//猫的有参构造方法
/* public Cat(String name,int age,String color){ //Cat c = new Cat("哆啦A梦",5,"蓝色");
super(name,age,color); //访问父类的有参构造方法
}*/
//alt+ins--->constructor--->将两个构造方法全部提供
public Cat() {
}
public Cat(String name, int age, String color) {
super(name, age, color);
}
//猫的特有功能
public void catchMouse(){
System.out.println("猫会抓老鼠");
}
}
package com.qf.extends_07;
/**
* 狗类
*/
public class Dog extends Animal{
//无参/有参构造方法
public Dog() {
super();
}
public Dog(String name, int age, String color) {
super(name, age, color);
}
//狗的特有功能
public void lookDoor(){
System.out.println("狗会看门");
}
}
static关键字
/**
* 关于static关键字--->被多个对象"共享,共用"的意思
*
*
* 特点:
* 1)被static修饰的成员(变量/方法)随着类的加载而加载,优先于对象存在! (对象创建: 类名 对象名 = new 类名() ;)
* 某个类要先被编译产生-->类名.class--->类在运行的时候,加载过程要将静态的成员都先进入方法区的静态区中!
* 2)static和this不能共存!
* this:代表是当前类对象的地址值引用---说明对象创建完毕,才能使用this.变量名 -->访问成员变量 (对象成员)
* static:随着类的加载而加载,被static修饰的成员--->"类成员"
* 3)如果有一个变量体现出被共享,被共用--->此时用"static"修饰
*
* 举例:
* 水杯中的水 (不行)
* 饮水机的水(可以被共享)
* 4)访问方式:(必须记住)
* 类成员--->被static修饰的,特有访问 方式
* 类名.变量名; //在访问本类中静态变量
* 类名.方法名() ;//在访问本类中的静态方法
*
* 注意:
* 我们所说的成员变量/成员方法---->默认 非静态的!
*
*/
//定义一个Demo类
class Demo{
//定义一个非静态成员变量
public int num = 100 ;
//静态的变量(静态成员变量)
public static int num2 = 50 ;
//非静态的成员方法
public void method(){
System.out.println("method Demo...");
}
//静态的成员方法(类方法)
public static void function(){
System.out.println("function Demo...");
// method() ; //这个方法非静态的
// System.out.println(num);
// System.out.println(num2) ;
}
}
//测试类
public class StaticDemo {
public static void main(String[] args) {
//需求:要访问Demo类中num和num2这个变量?
//创建Demo类对象
Demo d = new Demo() ;
System.out.println(d.num) ;
//System.out.println(d.num2) ; //可以访问,不建议这种方式
System.out.println(Demo.num2);//静态--都被类名访问
System.out.println("------------------------------------") ;
//访问method方法
d.method();
// d.function() ;//可以访问,不建议这种方式
Demo.function(); //访问静态方法
//jdk提供的Math:针对数学运算的工具类
//double random = Math.random();//静态发那个发
}
}
static的注意事项
/**
*静态static的使用注意事项:
-
1)非静态的成员方法里面,皆可以访问静态的变量/方法,也可以访问非静态的变量/方法!
-
2)静态的方法只能访问静态的成员,不能访问静态的
-
记住: 静态只能访问静态!
*/
//定义类Code
class Code{
//非静态变量
public int x = 10 ;
//静态变量:
public static int y = 20 ;
//非静态的成员方法
public void show(){
//访问x
System.out.println(x) ;
//静态变量
System.out.println(y) ;
}
//静态方法
public static void function(){
System.out.println("function Code...");
}
//静态的方法
public static void method() {
//访问非静态变量x
// System.out.println(x) ;
//访问静态的变量y
System.out.println(y);
System.out.println("-------------下面调用方法了--------------");
//show() ; //非静态方法
function();//静态方法
}
}
//测试类
public class StaticDemo2 {
public static void main(String[] args) {
//创建Code类对象
Code code = new Code() ;
code.show();
System.out.println("------------------------------");
//直接调用静态方法
Code.method();
Code.function();
System.out.println("------------------------------");
//int add = sum(10,20) ;
}
/*public static int sum(int a,int b){
return a+b ;
}*/
}
工具类
/**
* 定义数组工具类ArrayTool
* 工具类中方法都是静态的,而且构造方法私有的
*
*/
public class ArrayTool {
//提供无参构造方法,无参构造私有化---目的就是为了让外界类不能创建对象!
private ArrayTool(){}
//遍历功能--->全部加入static
public static void printArray(int[] array){
System.out.print("[") ;
//遍历数组
for (int i = 0; i < array.length; i++) {
if(i == array.length-1){
System.out.println(array[i]+"]");
}else{
System.out.print(array[i]+", ");
}
}
}
}
/**
* 需求:
* 已知一个数组,静态初始化,给数组中加入遍历功能,进行测试!
* 从最早开始定义方法--->面向对象的访问方式的过程!
*
*/
//测试类
public class ArrayTest {
public static void main(String[] args) {
//已知一个数组,静态初始化
int[] arr = {54,87,29,32,13} ;
//遍历
// printArray(arr) ;//传递数组对象
System.out.println("---------------------优化1---------------------------");
//就把printArray的方法的static去掉
//printArray()就是ArrayTest类中成员方法
//创建ArrayTest类对象
//ArrayTest at = new ArrayTest() ;
//at.printArray(arr) ;
System.out.println("---------------------优化2---------------------------") ;
//上面代码可以访问,但是:测试类中一般都是测试别的类,不会创建自己的类对象去访问
//而且,测试类中只有main方法
//创建ArrayTool类对象
// ArrayTool at = new ArrayTool() ;
//at.printArray(arr) ;
System.out.println("---------------------优化3:功能定义工具类中,工具类构造方法私有化---------------------------") ;
//使用类名.静态方法名() ;
ArrayTool.printArray(arr) ;
}
/*
* 定义一个遍历功能
* */
//静态方法
/*public static void printArray(int[] array){
System.out.print("[") ;
//遍历数组
for (int i = 0; i < array.length; i++) {
if(i == array.length-1){
System.out.println(array[i]+"]");
}else{
System.out.print(array[i]+", ");
}
}
}*/
//非静态
/* public void printArray(int[] array){
System.out.print("[") ;
//遍历数组
for (int i = 0; i < array.length; i++) {
if(i == array.length-1){
System.out.println(array[i]+"]");
}else{
System.out.print(array[i]+", ");
}
}
}*/
}
文档说明书
import java.lang.reflect.Array;
/**
* 需求:
* 已知一个数组,静态初始化,给数组中加入遍历功能,进行测试!
* 从最早开始定义方法--->面向对象的访问方式的过程!
*
*
* 自定义一个类工具类,构造方法私有化,对外提供静态的功能,对这个工具类产生 "文档说明书"
* 找到ArrayTool.java文件所在的目录
* 在dos窗口中输入指令
* javadoc -d 目录名称 -author -version java源文件名称 (前提条件是这个ArrayTool类必须是public修饰)
*
* 举例:
* javadoc -d doc -author -version ArrayTool.java
*
*
*
*/
//测试类
public class ArrayTest {
public static void main(String[] args) {
//已知一个数组,静态初始化
int[] arr = {54,87,29,32,13} ;
//调用ArrayTool类的所有静态功能
int max = ArrayTool.getArrayMax(arr);
System.out.println("最大值是:"+max);
System.out.println("------------------------------");
ArrayTool.bubleSort(arr) ;
//遍历
ArrayTool.printArray(arr );
System.out.println("-------------------------------");
ArrayTool.reverseArray(arr);
//遍历
ArrayTool.printArray(arr);
System.out.println("--------------------------------");
//逆序值,查询13这个元素第一次出现的角标
int index = ArrayTool.getIndex(arr, 13);
System.out.println(index);
int index2 = ArrayTool.getIndex(arr,300) ;
System.out.println(index2);
}
}
package com.qf.static_03;
/**
* ArrayTool这个类是自定义针对数组操作的工具类
* 里面提供了数组遍历,求数组最值,查询指定元素第一次索引值,逆序,冒泡排序等等这些功能
* @author 高圆圆
* @version V1.0
* */
public class ArrayTool {
//提供无参构造方法,无参构造私有化---目的就是为了让外界类不能创建对象!
private ArrayTool(){}
/**
* 这功能是对数组进行遍历的功能,
* 最终数组以[元素1, 元素2, 元素3, ...元素n]形式出现
* @param array 传递的数组
*
* */
public static void printArray(int[] array){
System.out.print("[") ;
//遍历数组
for (int i = 0; i < array.length; i++) {
if(i == array.length-1){
System.out.println(array[i]+"]");
}else{
System.out.print(array[i]+", ");
}
}
}
/**
*该方法是针对数组的求最大值的功能
* @param array 指定数组
* @return 返回值是表示数组中出现的最大值
* */
public static int getArrayMax(int[] array){
//定义中参照物
int max= array[0] ;
for(int x = 1 ; x < array.length ;x++){
if(array[x] > max){
max = array[x] ;
}
}
return max ;
}
/**
* 该功能是查询数组中的元素第一次出现索引值
* @param array 需要在指定数组中查询
* @param key 要查询指定的数组中的元素
* */
public static int getIndex(int[] array,int key){
//假设
int index = -1 ;
//遍历数组
for(int x = 0 ; x < array.length ; x++){
if(key== array[x]){
index = x ;
break ;
}
}
return index ;
}
/***
* 该功能是针对数组进行冒泡排序,两两比较,将较大的值往后放,
* 第一次比较完毕,最大值出现在最大索引处!
* @param array 要输入指定数组进行冒泡排序
*/
public static void bubleSort(int[] array){
for(int x =0 ;x<array.length-1 ;x++){
for(int y = 0 ; y < array.length-1-x;y++){
if(array[y] > array[y+1]){
int temp = array[y] ;
array[y] = array[y+1] ;
array[y+1] = temp ;
}
}
}
}
/***
* 该功能是将数组逆序,将第一个元素和最后一个元素进行互换,第二个元素和倒数第二个元素互换
* 依次这样操作,将数组逆序
* @param array 传入指定数组进行逆序
*/
public static void reverseArray(int[] array){
for(int start = 0 ,end = array.length-1 ;start < end ;start++,end--){
int temp = array[start] ; //array[0]
array[start] = array[end] ; //array[array.lengtt-1]
array[end] = temp ;
}
}
}
小测试
package com.qf.test_08;
/**
* .(面向对象基础)写一个Worker 类,并创建多个Worker 对象。
* 1) 为Worker 类添加三个属性,1)String 类型的name,表示工人的姓名;
* int 类型的age,表示工人的年龄;3)double 类型的salary,表示工人
* 的工资。
* 2) 为Worker 类添加两个work 方法,一个无参,另一个带整数参数,表示
* 工人工作的时间(为多少小时)。
*
*
* Worker如下的属性的类型以及构造方法相关的参数
* name:String
* age:int
* salary:double
* Worker()
* work(hours:int)
*
* 在测试类中进行测试 工人类(属性私有化)
*/
public class Test1 {
public static void main(String[] args) {
//无参构造+setxxx(xx)/getXX()
Worker worker = new Worker() ;
worker.setName("唐伯虎9527");
worker.setAge(30) ;
worker.setSalary(10000.0) ;
worker.work(25);
System.out.println("---------------------");
//有参构造方法直接赋值
Worker w2 = new Worker("秋香",25,8000.0) ;
w2.work(8);
}
}
package com.qf.test_08;
/**
* 定义一个工人类
*/
public class Worker {
private String name ; //姓名
private int age ; //年龄
private double salary ;//工资
//定义无参构造方法
public Worker(){
}
public Worker(String name,int age, double salary){
this.name = name ;
this.age = age ;
this.salary = salary ;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
//Worker 类添加两个work 方法,一个无参,另一个带整数参数,表示
// 工人工作的时间(为多少小时)。
public void work(int hours){
System.out.println(name+",年龄是"+age+",工资是:"+salary+",已经工作了"+hours);
}
}
多态
/**
* 什么是多态?
* 从宏观角度去说:一个事物(能看到真实存在的)体现出的不同形态!
* 举例:
* 水--->固态 气态 液态
* 从内存角度去说:一个对象它的所在的类型的变化
* 举例:
* Cat c = new Cat() ; //创建一个只猫 从右边--->左边:猫是猫
* Animal a = new Cat() ; //堆内存是猫 从右边--->左边:猫是动物
*
* 前提条件:
* 1)必须存在继承关系,才能使用多态
* 2)必须存在方法重写,子类继承父类,部分功能将父类进行重写,比如:
* 动物都要吃和睡,具体的动物类:猫/狗/猪,吃和睡的动作不一样
* 3) 必须存在 父类引用指向子类对象 ----->多态的 "向上转型"
* class 父类名{}
* class 子类名 extends 父类名{}
* //多态测试---
* 父类名 对象名 = new 子类名() ;
*
*
*
* 父类名 对象名 = new 子类名() ;
* 多态的成员访问特点:
* 成员变量:编译看左,运行看左!
*
* 成员方法(默认都是非静态): 如果子类重写了父类的方法,编译看左,运行看右!
* 静态方法算不上重写,和静态的都是类成员! (访问方式都是类名来调用的)
*
* 构造方法:继承是多态的前提条件,所以在使用父类引用指向子类对象:Fu fu = new Zi() ;
* 还是要遵循"分层初始化",先让父类构造初始化,然后在是子类构造初始化!
*
*/
//父类
class Fu{
//成员变量
int age = 40 ;
public Fu(){
System.out.println("Fu的无参构造方法");
}
//成员方法
public void show(){
System.out.println("show Fu");
}
public void method(){
System.out.println("method Fu");
}
public static void function(){
System.out.println("function Fu");
}
}
//子类
class Zi extends Fu{
//成员变量
int age = 20 ;
public void show(){
System.out.println("show Zi");
}
public Zi(){
System.out.println("Zi的无参构造方法");
}
public void playGame(){
System.out.println("儿子会玩游戏");
}
//静态算不上重写
public static void function(){
System.out.println("function Zi");
}
}
//测试类
public class DuoTaiDemo {
public static void main(String[] args) {
//父类引用指向子类对象 --->格式 父类名 对象名 = new 子类名() ;
Fu f = new Zi() ;
//Zi zi = new Zi() ;
//System.out.println(zi.age) ;
System.out.println(f.age) ;
f.show() ;
//f.show2() ; //show2()在Fu类中不存在,编译看左
f.method() ;
//f.function() ;
//Fu.function();
//Zi.function();
//f.playGame() ;编译报错:父类中没有playGame方法
}
}
多态的好处
/**
* 多态的好处:
* 1)可以提供代码的复用性(由继承保证的)
* 2)可以提高代码的扩展性(健壮性)--->由多态保证
* 父类引用指向子类对象
*/
//动物类
class Animal{
public void eat(){
System.out.println("动物需要吃饭");
}
public void sleep(){
System.out.println("动物困了就需要休息");
}
}
//子类
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫趴着睡");
}
}
//狗类
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗侧着睡");
}
}
//子类
class Pig extends Animal{
@Override
public void eat() {
System.out.println("猪吃白菜");
}
@Override
public void sleep() {
System.out.println("猪躺着睡");
}
}
//优化方案2:定义一个动物工具类
class AnimalTool{
//为了让外界不能new,无参构造方法私有化
private AnimalTool(){}
//定义一个方法: 使用猫的功能
/* public static void useCat(Cat c){//形式参数是猫类型
c.eat();
c.sleep();
}
//定义一个方法:使用狗的功能
public static void useDog(Dog d){//形参参数是狗类型
d.eat();
d.sleep();
}
//定义一个方法:使用猪的功能
public static void usePig(Pig p){
p.eat();
p.sleep();
}*/
public static void useAnimal(Animal a){ //形式参数是引用类型--->父类指向子类对象
// 实际参数:Animal animal = new Cat();
a.eat(); //animal.eat() ;
a.sleep(); //animal.sleep() ;
}
}
//测试类
public class DuoTaiDemo2 {
public static void main(String[] args) {
//使用具体的子类操作
//养了一只狗--创建狗
Dog dog = new Dog() ;
dog.eat();
dog.sleep();
System.out.println("-------------------------------------------------");
//优化:在测试类中提供两个静态方法,方法形式参数传递狗或者猫
//有一只猫对象
Cat cat = new Cat() ; //有名字的对象
useCat(cat) ;
useDog(new Dog());
System.out.println("----------------------优化方案2------------------------------");
//上面代码不好: 随着具体的类越来越多,useXXX(具体的动物类型)方法就会很多,代码量很多!
//定义一个动物工具类 AnimalTool
//AnimalTool at = new AnimalTool();
/* AnimalTool.useCat(new Cat());
AnimalTool.useDog(new Dog());
Pig pig = new Pig() ;
AnimalTool.usePig(pig);*/
//上面代码继续优化:随着具体类型增加,AnimalTool中的静态功能,越来越多
//多态的特点:父类引用指向子类对象:可以提高代码的扩展性
Animal animal = new Cat() ; //堆内存指向的是猫 (猫是的动物)
AnimalTool.useAnimal(animal);
animal = new Dog(); //堆内存是狗 (狗是动物)
AnimalTool.useAnimal(animal);
}
//定义一个方法: 使用猫的功能
public static void useCat(Cat c){//形式参数是猫类型
c.eat();
c.sleep();
}
//定义一个方法:使用狗的功能
public static void useDog(Dog d){//形参参数是狗类型
d.eat();
d.sleep();
}
}
多态的弊端
/**
* 多态的弊端:
* 不能访问子类的特有功能 父类名 对象名 = new 子类名() ; "向上转型"
*
* 如何解决呢?
* 方案1:
* 直接创建具体的子类对象 子类名 对象名 = new 子类名() ;
* 虽然可以这种方式可以,但是从内存角度考虑:消耗资源,浪费空间,又需要去开辟堆内存!
* 方案2:
* 多态本身:父类引用指向子类对象,能不能将父类的引用转换成子类型?
* "向下转型"---->强转类型转换的格式 ,前提必须有"向上转型"
* 数据类型 变量名 = (目标数据类型)(初始化值或者表达式) ;
*
*
*/
//父类
class Fu{
public void show(){
System.out.println("show Fu");
}
}
//子类
class Zi extends Fu{
public void show(){
System.out.println("show Zi");
}
//特有功能
public void playGame(String gameName){
System.out.println("会玩"+gameName+"游戏");
}
}
//测试类
public class DuoTaiDemo3 {
public static void main(String[] args) {
//父类引用指向子类对象
Fu fu = new Zi() ;
fu.show() ;
//fu.playGame("csgo") ;无法使用playGame方法()父类没有
System.out.println("-----------------------------") ;
//访问子类特有功能
// Zi z = new Zi() ;
//z.playGame("战地5");
System.out.println("------------------------------");
/**
* "向下转型"---->强转类型转换的格式 ,前提必须有"向上转型"
* * 数据类型 变量名 = (目标数据类型)(初始化值或者表达式) ;
*/
Zi z2 = (Zi)fu;
z2.playGame("战地5");
}
}
/**
* 多态的弊端:不能访问子类特有方法,通过向下转型来访问,这种方式节省内存;
* 但是向下转型使用不当,会出现运行时期的异常
*
*/
//动物类
class Animal{
public void eat(){
System.out.println("eat");
}
}
//猫
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
//狗
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
//测试类
public class DuoTaiDemo4 {
public static void main(String[] args) {
//多态的测试:父类引用指向子类对象
Animal a = new Cat() ;//堆内存是猫 (猫是动物)
//向下转型: 还原猫 (猫是猫)
Cat c = (Cat) a;
a = new Dog () ; //堆内存是狗 (狗是动物)
Dog d = (Dog) a; //还原成狗 (狗是狗)
a = new Cat() ;
//Dog dd = (Dog) a; //ClassCastException:类转换异常
Cat cc = (Cat) a;
}
}
方法重写
/**
* 继承关系中,成员方法的访问
* 子类继承父类,如果子类和父类的方法名不一致,分别调用即可! (简单)
*
* 如果子类出现了和父类一模一样的方法,如何访问呢?
* 子类会将父类的功能进行覆盖(复写/重写)--->override:方法重写
*/
class Fu{
//父类的成员方法
public void show(){
System.out.println("show Fu...");
}
}
//子类
class Zi extends Fu{
//成员方法
public void method(){
System.out.println("method Zi....") ;
}
public void show(){
super.show(); //既沿用了父亲的功能,还有自己的功能!
System.out.println("show zi...");
}
}
//测试类
public class ExtendsDemo {
public static void main(String[] args) {
//创建子类对象
Zi z = new Zi() ;
z.show() ;
z.method() ;
}
}
举例
/**
* 需求:
* 有个一个手机,具备打电话的功能;
*公司后期研发了新手机,这个手机不仅能够打电话,还能看天气预报
*
*
* 子类继承父类,在有的时候,子类想沿用父类的功能,但是使用的自己的功能,
* 子类出现了和父类一模一样的方法,这种叫 "方法重写--override"
*/
//手机
class Phone{
//具备打电话的功能
public void call(){
System.out.println("手机打电话了...");
}
}
//新手机 ---属于手机
class NewPhone extends Phone{
//这个手机不仅能够打电话,还能看天气预报
public void call() {
super.call(); //访问父类的call方法
System.out.println("该手机还可以看天气预报!");
}
}
//测试类
public class ExtendsDemo2 {
public static void main(String[] args) {
//创建具体的子类
NewPhone np = new NewPhone() ;
np.call();
}
}
举例
package com.qf.test_05;
/**
* 设计一个台灯类(Lamp)其中台灯有灯泡类(Buble)这个属性,
* * 还有开灯(on)这个方法
*/
public class Lamp {
//有一个灯泡类属性
private Buble buble;
/**
* 开灯的方法
* 请设计出一段代码可以使台灯开启灯泡发亮
*/
/* public void on(RedBuble redBuble){
redBuble.shine() ;
}
public void on(GreenBuble greenBuble){
greenBuble.shine() ;
}*/
//多态:父类引用指向子类对象,on这个方法形式参数传递父类型,
public void on(Buble buble){//Buble b = new RedBuble() ;
System.out.println("台灯开启...");
buble.shine() ;
}
}
package com.qf.test_05;
/**
* 有一个灯泡类
*
* 抽象的灯泡类
*/
public abstract class Buble {
//灯泡类有发亮的方法
/* public void shine(){
System.out.println("灯泡会亮");
}*/
//发亮的方法需要被子类进行重写
public abstract void shine() ;
}
package com.qf.test_05;
/**
* 绿灯泡
*/
public class GreenBuble extends Buble{
@Override
public void shine() {
System.out.println("灯泡可以发绿光了...");
}
}
package com.qf.test_05;
/**
* 红灯泡
*/
public class RedBuble extends Buble{
@Override
public void shine() {
System.out.println("灯泡可以发红光了");
}
}
package com.qf.test_05;
import com.sun.org.apache.regexp.internal.RE;
/**
* 设计一个台灯类(Lamp)其中台灯有灯泡类(Buble)这个属性,
* 还有开灯(on)这个方法。设计一个灯泡类(Buble),
* 灯泡类有发亮的方法,其中有红灯泡类(RedBuble)和绿灯泡类(GreenBuble)
* 他们都继承灯泡类(Buble)一个发亮的方法,请设计出一段代码可以使台灯开启灯泡发亮
* 红灯泡发红光,绿灯泡发绿光!
*
*
*/
public class Test5 {
public static void main(String[] args) {
//创建一个台灯
Lamp lamp = new Lamp() ;
//多态测试红灯泡
// Buble b = new RedBuble() ;
//lamp.on(b) ;
//匿名对象
lamp.on(new RedBuble());
System.out.println("-----------------------------");
Buble b = new GreenBuble() ;//抽象类多态
lamp.on(b) ;
System.out.println("----------------------------------");
lamp.on(new GreenBuble()) ;
}
}
关键字final
/**
*
* 定义一个父类,子类重写父类的某个成员方法,通过方法重写,最终子类将父类将父类方法覆盖
* 但是有的时候,父类不让子类将自己的某个成员方法进行重写(为了父类的方法的安全性!),Java提供了关键字--->final
*
* final:是一个状态修饰符 (最终的,无法更改的)
*
*
*/
//定义一个父类
class Fu{
//成员方法
public final void show(){ //加入final,这个show方法 最终的方法/无法更改的方法
System.out.println("这是一个绝密文件,任何不得更改!");
}
/* public void show(){
System.out.println("这是一个绝密文件,任何不得更改");
}*/
}
//定义一个子类
class Zi extends Fu{
/* public void show(){
System.out.println("这一堆垃圾...");
}*/
}
//测试类
public class FinalDemo {
public static void main(String[] args) {
//创建子类对象
Zi z = new Zi() ;
//调用show方法
z.show() ;
}
}
final的特点
/**
*final关键字特点:
* 基本概念:最终的/无法更改的
*
* 1)修饰类,该类不能够被继承!(当前这个类是最终类,无法来提供派生类(子类))
* 2)修饰成员方法,该成员方法不能重写(保证父类的方法安全性!)
* 3)修饰变量,此时该变量一个常量,不能在重新赋值!
*
*
*
* 常量:
* 编译时期常量---->基本数据类型:四类八种 (jvm不需要加载)
* public static final int a = 10 ;
* 运行时期常量---->引用数据类型: (jvm进行加载,引用类型 除过String)
* int类型--->包装类 类型 Integer类
* public static final Integer i = new Integer(10) ;
* //i = new Integer(100) ;//报错
*
* 开发中自定义常量:
* public static final 数据类型 变量名 = 初始化值;
*
*/
//定义一个类
//final class Animal{} //动物类
//子类:猫类
//class Cat extends Animal{}
//父类
class Father{
public static final int age = 20 ; //final修饰成员变量,必须给值,此值不能更改!
public final void method(){
System.out.println("method Father..");
}
}
//子类
class Son extends Father{
/*public void method(){//不能重写
System.out.println("method Son");
}*/
public void show(){
final int a = 100 ; //局部变量
//a = 200 ;//数据值不能在更改
System.out.println(a) ;
}
}
//测试类
public class FinalDemo2 {
public static void main(String[] args) {
System.out.println(Father.age); //访问父类中静态常量
}
}
final修饰基本数据类型与引用数据类型的区别(面试题)
package com.qf.final_04;
/**
- 面试题:
- final修饰基本数据类型和修饰引用数据类型 的区别?
-
final修饰的引用数据类型,当前不能在开辟堆内存(不能重新new),里面的成员变量依然可以进行赋值
-
final修饰的基本数据类型,基本数据数据值不能在改变!
*/
//定义一个学生类
class Student{
int age = 20;
}
//测试类
public class FinalDemo3 {
public static void main(String[] args) {
//创建学生类
//学生对象s没有加入任何修饰符
Student s = new Student() ;
System.out.println(s.age) ;
s.age = 30 ;
System.out.println(s.age);
System.out.println("----------------------------") ;
//创建一个新的学生对象
final Student s2 = new Student() ; //final修饰的引用数据类型,当前不能在开辟堆内存(不能重新new)
System.out.println(s2.age) ;
s2.age = 40 ;
System.out.println(s2.age) ;
//s2 = new Student() ;
System.out.println("----------------------------") ;
int a = 100 ;
a = 200 ;
System.out.println(a) ;
System.out.println("-------------加入final修饰基本类型-------------------") ;
final int num = 200 ;
//num = 50 ;
}
}
注意事项 用idea快捷键生成子类的构造方法时,如果子类有私有属性,记得自己添加一个无参构造方法
举例
package com.qf.test_02;
/**
* 假如我们在开发一个系统时需要对员工类类进行设计,程序员是员工,包含3个属性:姓名、工号以及工资。
* 经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。
* 请使用继承的思想设计出程序员类和经理类。要求类中提供必要的方法进行属性访问。
* (使用继承方式来完成代码编写,并在测试类中测试,明天讲)
*
* 分析:
* 程序员--->姓名,工号,工资---属性私有化--->对外通过setXXX(xx)/getXX()
* 经理----姓名,工号,工资 ---属性私有化--->对外通过setXXX(xx)/getXX()
* 特有属性:奖金
* 将共性内容抽取到一个类中--------->员工类
*
* 让程序员:
* Programmer 继承 Employee
* Manager 继承 Employee
*/
//员工类的测试类
public class EmployeeTest {
public static void main(String[] args) {
//测试经理
//无参构造+setXXX(xx)/getXXX()
Manager manager = new Manager() ;
manager.setName("高圆圆") ;
manager.setEmpId("007") ;
manager.setSalary(7999.99);
//自己的奖金属性,赋值
manager.setBonus(2000.00);
System.out.println(manager.getName()+"---"+manager.getEmpId()+"---"+manager.getSalary()+"---"+manager.getBonus());
manager.work();
manager.business();
System.out.println("------------------------------------------") ;
//有参构造方法创建经理类对象
Manager m2 = new Manager("唐伯虎","9527",8500.00,1000.0) ;
System.out.println(m2.getName()+"---"+m2.getEmpId()+"---"+m2.getSalary()+"---"+m2.getBonus());
m2.work();
m2.business();
//程序员自己测试
}
}
package com.qf.test_02;
/**
* 员工类
*/
public class Emplyee {
//姓名,工号,工资
private String name ;
private String empId ;
private double salary ;
//无参/有参构造
public Emplyee() {
}
public Emplyee(String name, String empId, double salary) {
this.name = name;
this.empId = empId;
this.salary = salary;
}
//提供setXXX(xx)/getXXX()
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
//定义一个成员方法
public void work(){
System.out.println("员工都需要工作!") ;
}
}
package com.qf.test_02;
/**
* 经理类
*/
public class Manager extends Emplyee{
// 特有属性:奖金
private double bonus ;
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
//无参/有参构造
public Manager(double bonus) {
this.bonus = bonus;
}
public Manager(){}
public Manager(String name, String empId, double salary,
double bonus) {
super(name, empId, salary); //"唐伯虎" ,"9527",8500.99,1000.0
this.bonus = bonus;
}
//特有功能
public void business(){
System.out.println("谈项目");
}
//子类和父类出现了一模一样的方法
public void work(){
super.work();
System.out.println("经理喝酒吃饭,找项目");
}
}
package com.qf.test_02;
/**
* 程序员类
*/
public class Programmer extends Emplyee{
public Programmer() {
}
public Programmer(String name, String empId, double salary) {
super(name, empId, salary);
}
//特有功能
public void coding(){
System.out.println("日日夜夜敲代码");
}
@Override //jdk提供注解(注解不是注释):
//@Override:标记当前这个方法是重写父类的方法
public void work() {
super.work();
System.out.println("程序员日日夜夜看需求,根据需求写代码");
}
}
成员变量定义问题
/**
* 变量--->成员变量/局部变量
* 什么时候将一个变量定义为成员变量?
*
* 需求:
* 定义一个类,定义成员方法,对两个数据求和!
*
* 将一个变量定义为成员变量的时机:
* 如果这个变量能够描述现实世界事物的属性--->定义为成员变量,否则都是"局部变量"
*/
class Demo{
//成员变量
/*
int a ;
int b ;
//定义一个成员方法
public int sum(){
return a + b ;
}
*/
public int sum(int a,int b){
return a + b;
}
}
//测试类
public class VariableDemo {
public static void main(String[] args) {
//访问Demo类中的sum方法
/* Demo d = new Demo() ;
d.a = 10 ;
d.b = 20 ;
int result = d.sum();
System.out.println(result);*/
Demo d = new Demo() ;
int reuslt = d.sum(10, 20);
System.out.println(reuslt);
}
}
抽象abstract
/**
* 什么是抽象?
* 举例:
* 将猫和狗的共性内容,抽取到了动物(本身就是统称,概括性的)了中,比如:吃和睡的功能,但是在动物了中
* 将吃和睡给出了具体体现,只有看到具体的事物才能知道它具体吃和睡的行为!所以在父类将这些行为,只是给出一个方法声明即可!
* 仅仅给出方法的声明---->含义没有方法体{},抽象功能---->
*
* 有抽象的方法的必须为抽象类
* 抽象类中不一定都是抽象方法!(部分的功能,抽象功能,必须让子类必须重写!)
*
* 抽象方法(成员方法)的格式:
* 权限修饰符 abstract 返回值类型 方法名(空参/带参) ;
*
* 抽象类的本质:
* 强制子类必须将父类的所有的抽象方法,必须实现(重写)
*抽象类的特点:
* 1)不能实例化(不能new 创建对象)
* 2)抽象类的子类一定有具体类,否则无法进行实例化的!
*
*
*
*/
//定义动物类
abstract class Animal{
/*public void eat(){
System.out.println("动物都需吃饭");
}*/
//将动物的吃的功能,给出一个声明即可,没有方法体{}
public abstract void eat() ;
public void show(){
System.out.println("show Animal");
}
}
//子类
//abstract class Cat extends Animal{//子类也是一个抽象类,肯定是有个具体的类的,进行父类的实例化!
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
//测试类
public class AbstractDemo {
public static void main(String[] args) {
//创建父类对象
//Animal a = new Animal() ; //不能new ,抽象类
//如何实例化:通过子类(最底层的子类:可以new的)进行实例化
Animal a = new Cat() ;//父类引用指向子类对象 (抽象类多态!)
a.eat() ;
}
}
抽象特点
/**
* 抽象类的成员特点:
* 1)成员变量:
* 可以是变量也可以自定义的常量
* 2)成员方法
* 既可以有抽象方法,也可以有非抽象方法!
* 3)构造方法
* 还存在继承关系,分层初始化--->先父类构造初始化,然后是子类构造初始化!
* 无参构造方法/有参构造方法都可以存在,目的都是为了数据进行初始化!
*/
//定义一个父类
abstract class Fu{
//定义一个成员变量
public int num = 20 ;
//自定义常量
public static final int num2 = 30 ;
//非抽象方法
public String show(){
return "hello,Show Fu!" ;
}
//抽象方法
public abstract void function() ;
public Fu(){
System.out.println("Fu的无参构造方法");
}
}
//子类
class Zi extends Fu{
//重写function
@Override
public void function() {
System.out.println("function Zi...");
}
public Zi(){
System.out.println("Zi的无参构造方法");
}
public Zi(String str){
System.out.println("Zi的有参构造方法");
}
}
//测试类
public class AbstractDemo2 {
public static void main(String[] args) {
//抽象类多态测试
Fu fu = new Zi() ; //父类引用指向子类对象
System.out.println(fu.num) ;
System.out.println(Fu.num2) ;
System.out.println("--------------------------------") ;
String result = fu.show() ;
System.out.println(result) ;
fu.function() ;
System.out.println("-----------------------------------");
Fu fu2 = new Zi("hello") ;
}
}
abstract 与其他关键字
/**
* 抽象abstract关键字不能和哪些关键字共存?
*
* abstract不能和private共用:
* 被private修饰的只能在当前类访问,而abstract修饰的方法,它需要强制子类进行重写;
* abstract不能和static共用:
* abstract修饰的成员方法,需要被子类重写,还是抽象类多态进行实例化Fu fu = new Zi() ;
* 而static随着类的加载而加载(静态方法算不上重写),跟类相关的!
* abstract不能和final共用:
* 被final修饰的成员方法不能被重写,而abstract修饰的成员方法,强转子类重写!
*
*
* abstract:用在类上,标记这个类----抽象类
* 用在方法上,标记这个方法是一个抽象方法!
* 结合public使用居多
*/
//定一个类
abstract class Animal2{
//定义一个抽象方法
//动物都需要吃
public abstract void eat() ;
//private abstract void eat() ;
//public static abstract void show() ;
//public final abstract void show() ;
}
class Cat2 extends Animal2{
@Override
public void eat() {
System.out.println("猫吃鱼") ;
}
}
//测试类
public class AbstractDemo3 {
public static void main(String[] args) {
}
}
举例
package com.qf.abstract_07;
/**
* 动物类
*/
public abstract class Animal {//抽象类
private String name ; //动物名称
private int age ; //年龄
private String color ;//颜色
public Animal() {
}
public Animal(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
//eat和sleep仅仅给出声明
public abstract void eat () ;
public abstract void sleep() ;
}
package com.qf.abstract_07;
/**
* 猫狗案例---自己分析属性和行为,加入方法重写,使用多态进行测试
* 猫和狗的共性属性:
* name,age,color
* setXXX(xx)/getXXX
* 猫特有功能:
* 抓老鼠
* 狗特有功能:
* 看门
*
* ---->抽取动物类中--抽象类
* eat()和sleep()---仅仅给出一个声明,此时抽象方法
*
* 使用多态进行测试(抽象类多态)
*/
public class AnimalTest {
public static void main(String[] args) {
//有参构造直接赋值
Animal a = new Dog("藏獒",6,"黑色") ;
System.out.println(a.getName()+"---"+a.getAge()+"---"+a.getColor());
a.eat();
a.sleep();
Dog d = (Dog) a;
d.lookDoor();
//无参构造方法+setXXX(xx)/getxx()展示信息 自己测试
}
}
package com.qf.abstract_07;
/**
* 猫类
*/
public class Cat extends Animal{
public Cat() {
}
public Cat(String name, int age, String color) {
super(name, age, color);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫趴着睡");
}
//特有功能
public String catchMouse(){
return "猫会抓老鼠" ;
}
}
package com.qf.abstract_07;
/**
*狗类
*/
public class Dog extends Animal{
public Dog() {
}
public Dog(String name, int age, String color) {
super(name, age, color);
}
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗侧着睡");
}
//特有功能
public void lookDoor(){
System.out.println("狗看门");
}
}
接口
/**
* 什么是接口?
*
* 举例:
* 猫或者狗本身这个事物不具备"跳高"的功能,经过后天 驯养员的培养,猫和狗就具备了"跳高的功能"
*
* 接口体现的是这个事物本身不具备的功能,是一种额外的扩展功能!
* 只要这个事物实现了接口,它就具备这个功能!
* 如何定义接口
* java定义接口
* interface 接口名{}
*
* 接口的子类(子实现类) implements 接口名{
* 强制子实现类必须将接口中所有抽象方法必须重写!(实现)
* }
*
* 接口的特点:
* 1)接口不能实例化(不能创建对象)
* 2)接口如何实例化?
* 接口多态
* 接口名 对象名 = new 接口的子实现类名() ; (前提:子实现类是非抽象的,就是一个具体类)
*
*
*开发中:
* 接口名和子实现类的命名规范(开发项目中)
* 举例:
* 接口名: interface Inter{}
* 接口的子实现类命名: 接口名 +Impl
* class InterImpl implements Inter{}
*
*
*
*/
//定义一个接口
interface Jump{
//定义一个跳高的功能
/*public void jump(){
System.out.println("可以跳高");
}*/
public abstract void jump() ;
}
//有一个动物类
abstract class Animal{
public abstract void eat() ;//抽象方法
}
//猫类
class Cat extends Animal implements Jump{ //猫 具备跳高的功能,必须实现接口
@Override
public void eat() {
System.out.println("猫吃鱼");
}
//跳高功能
@Override
public void jump() {
System.out.println("猫可以跳高了...") ;
}
}
//测试类
public class InterfaceDemo {
public static void main(String[] args) {
//创建接口Jump对象
// Jump jump = new Jump() ; //接口不能实例化(不能创建对象new)
// 接口名 对象名 = new 接口的子实现类名() ;
Jump jump = new Cat() ;//接口多态
jump.jump();
//jump.eat( );
//向下转型
Cat c = (Cat) jump;
c.eat();
}
}
接口中的成员特点
/**
* 接口中的成员特点:
* 成员变量:只能是常量 存在默认修饰符 public static final
* 成员方法:(非静态):只能是抽象方法,存在默认修饰符 public abstract
* 在接口中是可以定义静态方法,必须有方法体(特例)
* 构造方法: 没有构造方法! 因为子实现类和接口的关系是implements实现关系,
* 只是将接口暴露的额外功能进行实现!
*
*
*/
//定义一个接口
interface Inter{
/*public Inter(){
}*/
// public int num = 10 ;
public static final int num = 10 ;
//public static int num2 = 20 ;
public static final int num2 = 20 ;
/*void show(){//接口只能抽象方法
}*/
public abstract void show() ;
void show3() ;
//静态方法
public static void show2(){
System.out.println("show2()...");
}
}
//接口的子实现类 InterImpl实现Inter接口
class InterImpl implements Inter{
int num = 100 ;
@Override
public void show() {
System.out.println("show InterImpl");
}
@Override
public void show3() {
System.out.println("show3 InterImpl");
}
}
//测试类
public class InterfaceDemo2 {
public static void main(String[] args) {
//接口多态的测试
Inter inter = new InterImpl() ;
System.out.println(inter.num) ;//多态的成员变量的访问
System.out.println(Inter.num);
// inter.num = 200 ;
System.out.println(Inter.num2) ;
//inter.num2 = 300 ; final修饰的变量是一个常量,不能在赋值
Inter.show2();
}
}
类与接口
/**
* 在Java中,
* 类与类:
* 继承关系,extends,而且只支持单继承,不支持多继承,但是可以多层继承!
* 类与接口
* 实现关系,implements,而且一个类继承另一个类的同时,是可以实现多个接口的!接口名和接口名直接逗号隔开
* class LoverImpl extends Lover implements Love,Study{
* 接口与接口
* 继承关系,extends,不仅支持单继承,也支持多继承,也可以多层继承!
*
*/
//定义一个接口
interface Speak{
public abstract void speakEnglish() ;//会说英语
}
interface Study{
public abstract String study() ;//学习的功能
}
//接口
interface Love extends Study,Speak{
public abstract void love() ;
}
class Lover{
public void show(){
System.out.println("show Lover");
}
}
//实现类
//子实现类 实现接口
class LoverImpl extends Lover implements Love,Study{
@Override
public void love() {
System.out.println("爱生活,爱Java,爱高圆圆!");
}
//实现另一个接口的的功能
@Override
public String study() {
return "学习JavaEE!";
}
@Override
public void speakEnglish() {
System.out.println("会说英语....");
}
}
//测试类
public class InterfaceDemo3 {
public static void main(String[] args) {
//创建具体的子类对象
LoverImpl ll = new LoverImpl() ;
ll.show() ;//父类的方法
ll.love();
ll.study() ;
}
}
注意事项:如果子类访问父类的方法,父类方法里面访问的是子类重写父类的方法,
此时是访问子类的,而不是父类的。
方法的形式参数问题
/**
* 方法的形式参数问题: 只研究引用类型
*
* 方法形式参数:
* 具体类:调用该方法,此时实际参数需要的是当当前类的对象!
* 抽象类:调用该方法,此时实际参数需要的是当前抽象类的子类对象!
* 接口类型:调用该方法,此时实际参数需要的是接口的子实现类对象!
*
* 开发中:方法形式参数是具体类以及接口情况居多的!
*/
//具体类:调用该方法,此时实际参数需要的是当当前类的对象!
class Student{
public void studyJavaEE(){
System.out.println("正在学习JavaEE之JavaSE") ;
}
}
//定义一个StudentDemo类
class StudentDemo{
public void show(Student s){//方法的形式参数是一个学生类型
s.studyJavaEE() ;
}
}
//测试类
public class ArgsDemo1 {
public static void main(String[] args) {
//访问StudentDemo类中的show方法
StudentDemo sd = new StudentDemo() ;
Student student = new Student() ;
sd.show(student) ;
System.out.println("---------------------------------------") ;
//另一种方式:匿名对象
new StudentDemo().show(new Student());
}
}
//抽象类:调用该方法,此时实际参数需要的是当前抽象类的子类对象!
//定义一个Person类
abstract class Person{
/*public void work(){
System.out.println("人都需要工作");
}*/
public abstract void work() ;
}
//定义一个PersonDemo类
class PersonDemo{
public void function(Person p){//方法的形式参数是引用类型--抽象类,抽象类不能new,需要传递抽象类的子类对象!
p.work() ;
}
}
//定义抽象类的子类(具体类)
class Worker extends Person{
@Override
public void work() {
System.out.println("爱工作,爱Java,爱高圆圆!");
}
}
//测试类
public class ArgsDemo2 {
public static void main(String[] args) {
//访问PersonDemo类中的function方法?
PersonDemo pd = new PersonDemo() ;
//Person p = new Person() ;抽象类不能实例化(不能创建对象)
Person person = new Worker() ;
pd.function(person) ;
System.out.println("----------------------------------") ;
new PersonDemo().function(new Worker());
}
}
// 接口类型:调用该方法,此时实际参数需要的是接口的子实现类对象!
//定义一个接口
interface Love{
public abstract void love() ;
}
//定义一个类:LoveDemo
class LoveDemo{
public void method(Love love) {//方法的形式参数是一个接口? 接口不能new,需要接口的子实现类对象
love.love();
}
}
//需要有定义接口的子实现类,实现Love接口
class LoveImpl implements Love{
@Override
public void love() {
System.out.println("love Java!");
}
}
//测试类
public class ArgsDemo3 {
public static void main(String[] args) {
//要访问LoveDemo类中的method方法?
LoveDemo ld = new LoveDemo() ;
// Love l = new Love() ;//接口不能实例化
// ld.method(l);
//接口多态:接口名指向子实现类
Love l = new LoveImpl() ;
ld.method(l);
System.out.println("--------------------------");
new LoveDemo().method(new LoveImpl()) ;
}
}
方法的返回值问题
/**
* 研究的方法的返回值引用类型:
* 方法的返回值如果是引用类型:
* 具体类:需要返回该具体类的对象!
* 抽象类:需要返回该抽象类的子类对象!
* 接口:需要返回接口子实现类对象!
*/
class Demo{
//具体类:需要返回该具体类的对象!
//对两个数据求和
public int sum(int a,int b){
return a+ b;
}
}
//定义学生类
class Student{
public void study(){
System.out.println("好好学习,天天向上!");
}
}
//StudentDemo类
class StudentDemo{
public Student show(){
//?补全代码
//return Student ; 错误
//方式1:
// Student s = new Student() ;
//return s ;
//方式2:匿名对象
return new Student() ;
}
}
//测试类
public class ReturnDemo1 {
public static void main(String[] args) {
Demo d = new Demo() ;
int result = d.sum(10, 15);
System.out.println(result);
System.out.println("-------------------------");
//访问StudentDemo类中的方法
StudentDemo sd = new StudentDemo() ;
Student student = sd.show(); //show方法就是new Student()
student.study();
}
}
//抽象类:需要返回该抽象类的子类对象
//定义一个Person类
abstract class Person{
public abstract void work() ;
}
//PersonDemo类
class PersonDemo{
public Person function(){//方法的返回值是一个抽象类
//?
// return new Person() ; 抽象类不能实例化
//方式1:抽象类多态
//Person p = new Programmer() ;
//return p;
//方式2:直接匿名对象 (创建子类对象)
return new Programmer() ;
}
}
//定义一个类,继承Person
//程序员
class Programmer extends Person{
@Override
public void work() {
System.out.println("程序员日日夜夜敲代码!");
}
}
//测试类
public class ReturnDemo2 {
public static void main(String[] args) {
//访问PersonDemo类的function方法
PersonDemo pd = new PersonDemo() ;
Person person = pd.function(); //funciton方法 本质--->创建了子类对象
person.work();
}
}
//接口:需要返回接口子实现类对象!
//定义一个接口
interface Mary{ //结婚的接口
public abstract void mary() ;
}
//定义一个MaryDemo
class MaryDemo{
public Mary method(){
//?
//return new Mary() ;//接口不能new
//方式1:
//Mary mary = new MaryImpl() ;
// return mary ;
//方式2:
return new MaryImpl() ;
}
}
//需要定义接口的子实现类
class MaryImpl implements Mary{
@Override
public void mary() {
System.out.println("要结婚了,很开心...");
}
}
//测试类
public class ReturnDemo3 {
public static void main(String[] args) {
//需求:访问MaryDemo类中的method方法?
MaryDemo md = new MaryDemo() ;
Mary mary = md.method();
mary.mary();
System.out.println("--------------------------");
Mary mary2 = new MaryDemo().method();
mary2.mary();
}
}
内部类
package com.qf.innerclass_01;
/**
* 什么是内部类?
* 在Java中,在一个类中定义另一个类:
* 举例
* 在类A中,定义一个类B,将类B称为类A的内部类,类A是类B的外部类!
*
* 分类:
* 成员内部类:在类中,方法外定义的类
* 局部内部类:在方法定义中定义的类
*/
class Outer{
//成员内部类
/*class Inner{
public void show(){
System.out.println("show Inner");
}
}*/
//Outer的成员方法
public void method(){
//局部内部类
class Inner{
public void show(){
System.out.println("show Inner");
}
}
System.out.println("method Outer");
}
}
//测试类
public class InnerClassDemo {
}
成员内部类
/**
*成员内部类:
* 在外部类中,在外部类的成员方法外
*
* 特点:
* 可以访问外部类的成员包括私有!
*
*
* 直接去访问外部类的中的成员内部类的成员方法:特有方式 (成员内部类没有private以及static修饰!)
* 外部类.内部类名 对象名 = new 外部类名().new 内部类名() ;
*/
//外部类
class Outer2{
//成员变量
public int num = 20 ;
private int num2 = 50 ;
//成员内部类
class Inner2{
//成员方法
public void show(){
System.out.println(num) ;
System.out.println(num2) ;
}
}
//外部类的成员方法
public void method(){
// show() ; Outer2自己的show方法
//访问成员内部类的成员方法
//创建Inner2类对象
Inner2 in = new Inner2() ;
in.show() ;
}
}
//测试类
public class InnerClassDemo2 {
public static void main(String[] args) {
//创建外部类对象
//访问外部类的成员方法,间接的调用了成员内部类的成员方法
Outer2 ou = new Outer2() ;
ou.method() ;
System.out.println("--------------------------------------------------") ;
//测试类中:想直接去访问外部类里面的成员内部类的show
//外部类.内部类名 对象名 = new 外部类名().new 内部类名() ;
Outer2.Inner2 oi = new Outer2().new Inner2() ;
oi.show() ;
}
}
成员内部类与private
/**
* 成员内部类所涉及到的修饰符的问题:
* 有的时候不想让外部类直接去访问内部类的成员,为了保证内部类的成员安全,加入private
* 举例:
* 人有身体,身体有心脏;
* 伪代码
* class Body{
* //身体内有心脏
* //为了保证安全性,加入private修饰
* private class Heart{
* //成员方法
* public void operator(){
* System.out.println("心脏搭桥") ;
* }
* }
*
* //外部类的成员方法
* public void method(){
* if(你是外科医生){
* //创建Heart对象,去调用operator方法
* }
* }
*
*
* }
*
*
* //直接访问成员内部类中的operator方法
* 外部类名.内部类名 对象名 = new 外部类名().new 内部类名() ;
* Body.Heart bh = new Body().new Heart() ;会报错的
*
*
* 成员内部类可以使用过static修饰:
* 特点:静态的成员内部类它里面的所有 成员方法:
* 无论是静态的方法还是非静态的,访问外部类的成员:必须先为静态
*
* 想直接去访问静态的成员内部类的这些成员方法:??
*
* 外部类名.内部类名 对象名 = new 外部类名.内部类名();
*
*/
//外部类
class Outer3{
private int num = 100;
public static int num2 = 20 ;
//静态修饰
static class Inner3{ //Inner3现在看成是外部类的静态成员!
//非静态的方法
public void show(){
// System.out.println(num) ;
System.out.println(num2) ;
System.out.println("show Inner3");
}
//静态的方法
public static void show2(){
System.out.println(num2) ;
//System.out.println(num) ;
System.out.println("show2 Inner3");
}
}
}
//测试类
public class InnerClassDemo3 {
public static void main(String[] args) {
//访问成员内部类的成员方法
//外部类名.内部类名 对象名 = new 外部类().new 内部类名() ;
//Outer3.Inner3 oi = new Outer3().new Inner3() ; 用不了,只能针对非静态的成员内部类!
//针对静态的成员内部类:直接去访问里面的成员方法
//外部类名.内部类名 对象名 = new 外部类名.内部类名();
//如果是静态内部类的静态成员方法或静态成员变量
//外部类名.内部类名.方法名()或成员变量
Outer3.Inner3 oi = new Outer3.Inner3() ;//Inner3类看成是Outer3的静态成员
oi.show() ;
oi.show2() ;
System.out.println("----------------------------------------");
//show2()是静态的成员内部类的静态成员
Outer3.Inner3.show2();
}
}
局部内部类
package com.qf.innerclass_02;
/**
* 局部内部类:
* 在外部类的成员方法中定义的类
* 特点:
* 局部内部类也是可以直接访问外部类的成员变量,包括私有!
*
* 面试题:
* 局部内部类里面的成员在访问局部变量的时候,局部变量有什么要求?
*
* JDK8以前的版本,局部内部类在访问外部类的成员方法中的局部变量的时候,此时局部变量必须加入final修饰!
* 原因:
* 局部变量的生命周期随着方法调用而存在,随着方法调用结束而消失;
* 外部类的成员方法调用完毕,此时这个局部变量应该释放了,但是当前这个成员方法中创建局部内部类对象
* 使用局部内部类对象访问它里面的成员方法,成员方法还在使用这个局部变量,所以此时这个变量为常量,
* 显示的加入final修饰
* JDK8以及jdk8以后:优化了
* 可以通过反编译工具---->自动加入final,还是定义一个常量
*/
//外部类
class Outer{
private int num = 20 ;
//外部类的成员方法
public void method(){
int x = 200 ;
//局部内部类
class Inner{
//成员方法
public void show(){
System.out.println("show Inner") ;
System.out.println(num);
System.out.println(x) ;
}
}
//创建Inner
Inner inner = new Inner() ;
inner.show();
}
}
//测试类
public class InnerClassDemo {
public static void main(String[] args) {
//创建外部类对象
Outer outer = new Outer() ;
outer.method();
}
}
局部内部类细节
/**
* 面试题
* 在控制台分别打印
* 30
* 20
* 10
*
* 内部类外部类没有继承关系,不能使用super!
* 内部类(如果外部类名和内部类名以及局部变量有相同的变量名)
* 外部类名.this.变量名 表示外部类的变量
* this.变量名 表示内部类的变量
* 变量名 表示局部变量
*/
class Outer2{
int num = 10 ;
//成员内部类
class Inner2{
int num = 20 ;
public void show(){
int num = 30 ;
//补全代码
System.out.println(num) ; //就近原则
System.out.println(this.num) ; //访问本类的成员变量
// System.out.println(new Outer2().num) ; //创建外部类对象.变量名
//this:代表当前类---->Outer2.this--->外部类的this限定(访问的是外部类中的信息)
System.out.println(Outer2.this.num);
}
}
}
//测试类
public class InnerClassDemo2 {
public static void main(String[] args) {
Outer2.Inner2 oi = new Outer2().new Inner2() ;
oi.show();
}
}
匿名内部类(重点)
/**
* 匿名内部类:(没有名字的类)---是内部类的一种简化格式!
* 针对抽象类或者接口去使用的
* 匿名的格式
* new 类名(抽象类)或者接口名(){
* 重写类里面或者接口的抽象功能!
* } ;
* 应用范围:在局部位置中使用
*
* 匿名内部类的本质:
* 是继承了该抽象类或者是实现了接口子类对象!
*/
import com.sun.xml.internal.ws.addressing.WsaActionUtil;
//定义接口
interface Inter{
void show() ;
void show2() ;
}
//正常有一个接口的实现类
/*class InterImpl implements Inter{ //有名字的子实现类
@Override
public void show() {
System.out.println("show Inter...");
}
}
//在测试类中测试子实现类
Inter inter = new InterImpl() ;
inter.show();
*/
//Outer类
class Outer{
//外部类的成员方法
public void method(){
/**
* new 类名(抽象类)或者接口名(){
* 重写类里面或者接口的抽象功能!
* } ;
*/
/* new Inter(){
@Override
public void show() {
System.out.println("show Inter...");
}
@Override
public void show2() {
System.out.println("show2 Inter....");
}
}.show(); //调用接口的方法
new Inter(){
@Override
public void show() {
System.out.println("show Inter...");
}
@Override
public void show2() {
System.out.println("show2 Inter....");
}
}.show2();*/
//优化:给匿名内部类----起一个名字,使用对象名来访问
Inter inter = new Inter() {
@Override
public void show() {
System.out.println("show Inter");
}
@Override
public void show2() {
System.out.println("show2 Inter");
}
} ;
inter.show();
inter.show2();
}
}
//测试类
public class InnerClassDemo {
public static void main(String[] args) {
Outer outer = new Outer() ;
outer.method() ;
}
}
场景1
/**
* 匿名内部类在开发中的使用
* 作为形式参数
*/
abstract class Person{
public abstract void work() ;//人都需要工作
}
//PersonDemo类
class PersonDemo{
public void function(Person person){//形式参数是引用类型:抽象类不能实例化! 调用方法,实际参数需要的是抽象类的子类对象!
person.work() ;
}
}
//定义子类
class Programmer extends Person{
@Override
public void work() {
System.out.println("陈戌源日日夜夜敲代码!");
}
}
//测试类
public class ArgsDemo {
public static void main(String[] args) {
//要访问PersonDemo类中function方法?
PersonDemo pd = new PersonDemo() ;
//Person person = new Person() ;
//抽象类多态
Person p = new Programmer() ;
pd.function(p);
System.out.println("----------------------------") ;
//使用抽象类的匿名内部类
/**
* new 类名或者接口名(){
* //重写方法
* }
*
*/
pd.function(new Person(){
@Override
public void work() {
System.out.println("每个人工作性质不同!");
}
});
}
}
场景2
package com.qf.return_05;
/**
* 匿名内部类开发中使用场景2:
* 方法返回值是抽象类或者接口
*/
interface Love{
void love() ;
}
//LoveDemo
class LoveDemo{
public Love method(){ //返回是一个接口:返回接口的子实现类对象
//?如何返回
//接口不能new
//接口多态
//Love l = new LoveImpl() ;
//return l;
//return new LoveImpl() ;
//2使用接口的匿名内部类
/**
* new 类名或者接口(){
* //重写方法
* }
*/
return new Love() {
@Override
public void love() {
System.out.println("爱生活,爱Java,爱高圆圆!");
}
};
}
}
//定义一个子实现类
class LoveImpl implements Love{
@Override
public void love() {
System.out.println("love life,love 高圆圆");
}
}
//测试类
public class ReturnDemo {
public static void main(String[] args) {
LoveDemo ld = new LoveDemo() ;
Love love = ld.method(); //使用的接口匿名内部类的子实现类对象!
love.love();
}
}