第四周之抽象类,接口,内部类

第四周之抽象类,接口,内部类,第1张

第四周之抽象类,接口,内部类 1. 抽象类
1.如果一个类中,有抽象方法的话,那么这个类必须定义为抽象类
		抽象类格式:
			abstract class类名{}
  		抽象方法格式:
  			权限修饰符 abstruct 返回值类型 方法名(参数列表);
2.抽象类的本质:强制子类重写抽象方法
3.抽象类的特点:
		1.抽象类不能实例化,但是抽象类一定存在最具体的子类,否则没有意义
		2.抽象类中可以没有抽象方法(抽象类中没有抽象方法的意义:不能实例化)
4.抽象类的实例化
		通过抽象类多态,父类引用指向子类对象,有最具体的子类
5.抽象类的成员特点:
		(1)成员变量:可以是变量,也可以是自定义常量
		(2)成员方法:既可以是抽象方法(必须有abstract),也可以是非抽象方法
		(3)构造方法:存在继承关系,子类继承父类,分层初始化
6.abstract不能与那些关键字一起使用:
		(1)private:被private修饰的方法只能在当前类访问,而abstract需要子类重写
		(2)final:final关键字修饰的方法不能被重写
		(3)static:与类相关,随着类的加载而加载,而抽象方法需要被子类重写,最终需要使用对象来抽象化多态:Fu fu = new Zi();和static一起使用在父类中没有方法体,加载没有意义
		
2. 接口
1.接口是一种规范,就是能实现接口中的额外功能
	接口比抽象类还抽象的一种类型
2.格式:
		interface 接口名(大驼峰命名法){}
		class 子实例类名 implements 接口1,接口2...{}
		接口名 对象名 = new 子实例类名();
3.接口中的方法只能是抽象方法,不能有方法体
	特点:不能实例化,通过接口多态,所以具有具体的子类
4.接口中的成员特点:
		(1)成员变量只能是常量,存在默认修饰符: public static final(可以省略不写)
		(2)接口中的构造方法:没有构造方法
		(3)接口中的成员方法:只能是抽象方法,存在默认修饰符:public abstract(可以省略不写)
			// 默认方法,必须有方法体,接口自己的默认方法
			default void 方法名(){ 
				System.out.println("method Inter...");
			}
			//静态方法
			public static void 方法名(){
				System.out.println("function Inter...");
			}
5.关系的区别
		(1)类与类的关系:继承关系
		(2)类与接口关系:实现关系
			一个类继承自另一个类的时候,可以实现多个接口
		(3)接口与接口的关系:可以单继承,多继承,多层继承
3.形式参数问题
方法的形式参数:基本数据类型/引用数据类型
1.形参为基本数据类型,实际参数就是当前的数据值就行,而且形参的改变不会影响实际参数
2.形参为引用数据类型(空间地址值的传递)
		(1)具体类:实际参数应该创建当前具体类对象
    			class Student{
                    public void study(){
                        sout("学习Java");
                    } 
                }
				class StudentDemo{
                    public void method(Student student){
                        student.study();
                    }
                }
				class 测试类{
                    main(){
                    StudentDemo student = new StudentDemo();
                    Student a = new Student();
                    student.method(a);
                    sout("========================");
                    student.method(new Student());
                    sout("========================");
                    new StudentDemo.method(new Student());
                }
                }
		(2)抽象类:实际参数传递时创建当前抽象类的子类对象(抽象类多态)
            abstract class Student{
                    public abstract void study();           
                    } 
                }
				class Students extends Student{
                    public void study(){
                        sout("学习java");
                    }
                }
				class StudentDemo{
                    public void method(Student student){
                        student.study();
                    }
                }
				class 测试类{
                    main(){
                    StudentDemo student = new StudentDemo();
                    Student a = new Students();
                    student.method(a);
                    sout("========================");
                    student.method(new Students());
                    sout("========================");
                    new StudentDemo.method(new Students());
                }
                }
            (3)接口:传递接口实现类的对象
                interface Student{
                 public abstract void study();
            }
				class Students implements Student{
                    public void study(){
                        sout("学习java");
                    }
                }
				class StudentDemo{
                    public void method(Student student){
                        student.study();
                    }
                }
					class 测试类{
                    main(){
                    StudentDemo student = new StudentDemo();
                    Student a = new Students();
                    student.method(a);
                    sout("========================");
                    student.method(new Students());
                    sout("========================");
                    new StudentDemo.method(new Students());
                }
                }
		(4)数组:实际参数传递数组对象
            import java.util.Arrays;
			class Array{
                public void array(int[] arr){
                    sout(Arrays.toString(arr));
                }
            }
			class ArrayTest{
                main{
                    Array a = new Array();
                    int[] arr1 = new int[4];
                    a.array(arr1);
                }
            }
4. 返回值类型问题
返回值类型:基本数据类型/引用数据类型
1.返回值为基本数据类型,直接返回基本数据类型的返回值即可
2.返回值类型为引用数据类型
		(1)具体类:需要返回当前类的具体对象
			class Student{
                public void study(){
                    sout("学习java");
                }
            }
			class StudentDemo{
                public Student method(){
                    return new Student();
                }
            }
			class 测试类{
                main(){
                    StudentDemo a = new StudentDemo();
                   	Student b = a.method();
                    b.study();
                    sout("=============================");
                    new StudentDemo.method().study();
                    
                }
            }
		(2)抽象类:返回当前抽象类的子类对象
            abstract class Student{
                public abstract void study();
            }
			class Students extends Student{
                public void study(){
                    sout("学习java");
                }
            }
			class StudentDemo{
                public Student method(){
                    return new Students();
                }
            }
			class 测试类{
                main(){
                    StudentDemo a = new StudentDemo();
                    Student b = a.method();
                    b.study();
                    sout("=============================");
                    StudentDemo a = new StudentDemo();
                    a.method().study();
                     sout("=============================");
                    new StudentDemo.method().study();
                }
            }
		(3)接口:需要返回子实现类的对象
               interface Student{
                public abstract void study();
            }
			class Students implements Student{
                public void study(){
                    sout("学习java");
                }
            }
			class StudentDemo{
                public Student method(){
                    return new Students();
                }
            }
			class 测试类{
                main(){
                    StudentDemo a = new StudentDemo();
                    Student b = a.method();
                    b.study();
                    sout("=============================");
                    StudentDemo a = new StudentDemo();
                    a.method().study();
                     sout("=============================");
                    new StudentDemo.method().study();
                }
            }
5.内部类
1.内部类:
		(1)成员内部类:在外部类的成员位置定义的类
		(2)局部内部类:在外部类的成员方法中定义的类
		(3)静态内部类
2.访问成员问题
		(1)成员内部类:(前提:当前的成员内部类是非静态的)
			(可以用private修饰,保证数据安全)
			可以访问外部类的所有成员,外部类也可以访问内部类的变量和方法
			创建内部类对象的方法格式:
			外部类名.内部类名 对象名 = new 外部类名().new内部类名();
				class Outer{
                private String name = "张三";
                int age = 14;
                //内部类
                class Inner{
                    int n = 10;
                    public void show(){
                        sout(name+age+n);
                    }
                }
                //外部类成员方法
                public void method(){
                    Inner inner = new Inner();
                    inner.show();
                }
            }
				class 测试类{
                    main(){
                        Outer outer = new Outer();
                        outer.method();
                    }
                }
		(2)局部内部类:局部内部类可以访问外部类所有成员,但是局部内部类的成员只能在创建该局部类的方法中调用
            面试题:局部内部类访问局部变量的时候,能访问码?局部变量有什么要求?
                jdk7或者jdk7以前,局部变量必须显示加入final修饰,否则访问报错
                而jdk8已经jvm优化了,此时这个num2就是常量!---使用反编译工具查看内部类的结构--->发现其实已经加入了final
                局部变量的生命周期是随着的方法的调用而存在,随着方法的调用结束而消失;
				而当前这个方法结束之后,num2局部变量也应该就不存在了,但是我们还在使用内部类对象访问它里面这个成员方法,而对象不会立即被GC立即回收,等待空闲的时候回收没有更多引用的对象,所以此时这些变量应该都是常驻内存,使用final定义----->常量!
    class Outer4{
    private int num = 100 ;//外部类的成员变量
    //成员方法
    public void method(){
        //局部内部类
        class Inner4{
            //成员方法
            public void show(){

                //局部变量
                int num2 = 20 ;

                //局部内部类访问局部变量--->能访问吗?
                // --->此时这个变量有什么要求吗?--有
                System.out.println(num2) ;// 没有报错!
                System.out.println(num) ;//访问外部类的成员
            }
        }

        //在method方法中,访问show
        //创建局部内部类对象.show()
        Inner4  inner4 = new Inner4() ;
        inner4.show() ;
    }
}
	//测试类
	public class InnerClassDemo4 {
    public static void main(String[] args) {

        //创建外部类对象
        Outer4 outer4 = new Outer4() ;
        outer4.method() ;
    }
}
		(3)静态内部类:用static修饰的成员内部类
            		静态内部类只能访问外部类的静态成员,外部类访问静态内部类时,可以跳过外部类直接通过内部类访问静态内部类成员
            创建静态内部类对象的格式:
				外部类名.静态内部类名 变量名 = new 外部类名.静态内部类名();
5.权限修饰符和包
1.
           同类中        相同包不同类       不同包的子类         不同包的无关类
 private	√
 default	√				√
 protected	√				√				√
 piblic		√				√				√					√
 
 2.static在工具类中将构造方法私有化,里面方法加入static,类名访问
 
 3.包-----就是文件夹
 		真实的开发环境中包需要针对代码分层
 		代码分包:
 				(1)实体类--存储实体类(描述现实世界事物的)
                    com.qf.pojo/entity/domain
 						//属性私有化,对外提供get/set方法
                (2)service层--业务接口层
                    com.qf.service
                    	举例:UserService //用户注册功能
                             boolean register(User user) ;
							 boolean login(User user) ;
                    com.qf.service.impl--业务接口的实现
                        	UserServiceImpl实现上面的这些功能
                        	数据从数据库中访问
                        	在业务实现层中调用数据库访问层中的接口方法
                 (3)持久层(数据库访问层)
                      com.qf.dao
                        	UserDao接口
                        	数据访问的接口层//查询数据库中是否有User信息
                        	boolean sleectUser(User user) 
                      com.dao.impl
                        	UserDaoImpl实现层
                        	数据访问接口实现层
                        	boolean sleectUser(User user) {}
				 (4)控制层  controller层
                      com.qf.controller
                     		类名:UserController
                                代码--->调用业务层数据方法
                                就有业务数据--->利用前后端的交互技术
                                进行数据的视图的渲染!
4.带包的编译运行
               (1)手动方式:
					创建com文件夹
                        子文件夹qf
                    使用javac对源文件编译
                    将字节码文件放在qf子文件夹下
                    带包名运行
                        java 包名.字节码文件前缀
               (2)自动方式
                     javac -d . java文件-->自动产生文件夹和字节码文件
                     带包运行即可
6 匿名内部类
1.没有名字的类
2.使用场景:很少有为具体类的匿名内部类,因为具体类本身就可以new对象
		  一般都是抽象类和接口中使用最多
3.格式:
		//(一般是抽象类名或者接口类名)
		new 类名(){
            重写抽象类或者接口的抽象方法{
                
            }
        };------------->不能忘记分号
4.本质:就是继承了该抽象类或者实现了接口的子类对象
6.1实 *** 代码
1.有以下代码可看出
    	(1)使用常规方法我们需要写一个接口实现类,重写接口方法之后去调用方法
    	(2)使用匿名内部类不需要写接口实现类,直接采用匿名方式去调用方法
 		interface Inter{
    	void show();
    	void show2();
	}
	//定义一个外部类
	class Outer{
    public void method(){
        //1.常规用法
        class InterImpl implements Inter{        //访问方式为在方法体后.方法名
            public void show(){
                System.out.println("这是一个接口实现类");
            }
            public void show2(){
                System.out.println("这是一个接口实现类");
            }
        }
        class Demo{
            public void show3(Inter j){
                j.show();
                j.show2();
            }
        }
        Demo demo = new Demo();
        Inter inter = new InterImpl();
        demo.show3(inter);
        //2.采用匿名内部类
        //访问方式为在方法体后.方法名
        new Inter(){
            public void show(){
                System.out.println("这是一个匿名内部类");
            }
            public void show2(){
                System.out.println("这是一个匿名内部类");
            }
        }.show();
        new Inter(){
            public void show(){
                System.out.println("这是一个匿名内部类");
            }
            public void show2(){
                System.out.println("这是一个匿名内部类");
            }
        }.show2();
        //以上访问方式代码量过大,创建一个接口对象来接收
        Inter i = new Inter(){
            public void show(){
                System.out.println("这是一个匿名内部类");
            }
            public void show2(){
                System.out.println("这是一个匿名内部类");
            }
        };
        i.show();
        i.show2();
    }
}
//测试类
	public class InnerClassTest{
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.method();

    }
}

输出结果:
这是一个接口实现类
这是一个接口实现类
这是一个匿名内部类
这是一个匿名内部类
这是一个匿名内部类
这是一个匿名内部类

6.2 当方法的形式参数为接口类(抽象类相同)
1.方法的形式参数如果是一个接口类型,调用方法的时候,需要传递接口的子实现类对象

interface Inter{
    void show();
    void show2();
}
//定义一个类,实现接口的方法
class InterDemo{
    public void method(Inter inter){
        inter.show();
        inter.show2();
    }
}
//测试类
public class InnerClassTest{
    public static void main(String[] args) {
        //创建方法对象
        InterDemo demo = new InterDemo();
        demo.method(new Inter(){
            @Override
            public void show() {
                System.out.println("这是形式参数为接口类的方法");
            }

            @Override
            public void show2() {
                System.out.println("这是形式参数为接口类的方法");
            }
        });

    }
}

输出结果:
这是形式参数为接口类的方法
这是形式参数为接口类的方法
6.3方法返回值为接口(抽象类相同)
1.方法的返回值如果是一个接口,需要接口的子实现类对象
interface Inter{
    void show();
    void show2();
}
//定义一个类,实现接口的方法
class InterDemo {
    public Inter method() {
        return new Inter() {
            @Override
            public void show() {
                System.out.println("这是返回值为接口的匿名对象");
            }

            @Override
            public void show2() {
                System.out.println("这是返回值为接口的匿名对象");
            }
        };
    }
}
//测试类
public class InnerClassTest{
    public static void main(String[] args) {
        //创建方法对象
        InterDemo demo = new InterDemo();
        demo.method().show();
        demo.method().show2();
        System.out.println("========================");
        Inter inter = demo.method();
        inter.show();
        inter.show2();

    }
}
输出结果:
这是返回值为接口的匿名对象
这是返回值为接口的匿名对象
========================
这是返回值为接口的匿名对象
这是返回值为接口的匿名对象
6.4 拉姆达表达式
1.JDK8之后,当接口中只有一个抽象方法的时候,那么这个接口可以称为"函数式接口"
interface Love{
    void love() ;
}
class LoveDemo{
    public void show(Love l){//方法的形式参数是一个接口--->需要接口的子实现类对象
        l.love();
    }
}
//测试类
public class InnerClassTest2 {
    public static void main(String[] args) {
        //访问的是LoveDemo中的show方法
        LoveDemo ld = new LoveDemo() ;

        //当接口中有且仅有一个抽象方法的时候,那么这个接口可以称为"函数式接口"
        //函数式接口---->实现方法的时候---->有一个  -> 箭头直接可以实现接口的方法
        ld.show( //接口的匿名内部类很多

                () ->{
                System.out.println("爱生活,爱Java,爱高圆圆");
              }
            ) ;

    }
}

6.5匿名类面试题
 * 看程序,补全代码--->控制台输出"hello world"
 * 考点匿名内部类的使用
interface  Inter{
    void show() ;
}
class Outer{
    //以下为补全代码
    public static Inter method(){
        return new Inter(){
          public void show(){
              sout("hello world");
          }  
        };   
    }
}
public class Test {//测试类
    public static void main(String[] args) {
         Outer.method().show();
//分析思路-->Outer能够直接访问method,说明method是一个静态方法-->能够直接访问show方法,说明是有返回值
    }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5708645.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存