Java从入门到放弃10—方法参数类型以及返回值类型问题/链式编程/权限修饰符/内部类/内部接口

01 方法参数类型以及返回值类型问题

  • 类名作为形式参数:传入该类的一个对象
public class MyTest {
    public static void main(String[] args) {
        Student student = new Student();
        int num=2;
        set(student,num);
        student.show(new Student(),100);//传入的是一个新的匿名对象
        System.out.println(student.num);//打印前一个对象的num值2
    }

    public static void set(Student student,int num){
        student.num=num;
    }
}

class Student{
    int num=10;

    public void show(Student student,int num){
        student.num=num;
    }

}
运行结果2

  • 抽象类名作为形式参数:传入一个抽象类的子类对象
public class MyTest {
    public static void main(String[] args) {
        int num=1;
        Zi zi = new Zi();
        set(new Zi(),num);//形参为抽象类名,传入一个抽象类的子类对象
        zi.show(188);
        System.out.println(zi.num); //188
    }

    public static void set(Fu fu,int num){
        fu.num=num;
    }
}

abstract class Fu{
    int num=100;
    public abstract void show(int num);
}

class Zi extends Fu{
        int num=10;
    @Override
    public void show(int num) {
        this.num=num;
    }
}
运行结果:188

  • 接口名作为形式参数:传入一个实现该接口的子类对象
public class MyTest {
    public static void main(String[] args) {
        int num=1;
        B b = new B();
        set(b,num);//接口名作为形式参数,传入一个实现该接口的子类对象
        System.out.println(b);//打印对象b的地址值
        System.out.println(b.a);//set方法中调用了show方法,将b中的成员变量修改为传入的num值1
        System.out.println(b.NUM); //100
        System.out.println(A.NUM); //静态变量可以直接通过类名调用。打印100
        System.out.println(B.NUM); //B类实现了A接口,因此也可以直接通过类名调用到NUM。因此打印100

    }
    public static void set(A a,int num){
       new B().a=num;//创建了一个新的匿名对象
       a.show(num);//调用show方法
       System.out.println(a);//打印传入对象a的地址值,该地址值与对象b地址值相同

    }
}

interface A{
    public static final int NUM=100;
    void show(int num);
}

class B implements A{
        int a=10;

    @Override
    public void show(int num) {
        this.a=num;
    }
}
运行结果:org.westos.demo4.B@1540e19d
		org.westos.demo4.B@1540e19d
		1
		100
		100
		100

  • 类名作为返回值类型:返回该类的一个对象
public class MyTest {
    public static void main(String[] args) {
        int num = 100;
        A a = new A();
        A a1 = a.getA(num);//用对象a1接受返回值类型为类名的getAA方法,此时该对象的成员变量num为100
        System.out.println(a.num);// 1
        System.out.println(a1.num); // 100
        System.out.println(a);
        System.out.println(a1);
        System.out.println(a == a1);
        A a2 =getAA(a,num);
        System.out.println(a2.num);//100
    }

    public static A getAA(A a, int num) {
        a.num = num;
        return a;//返回的a就是传入的a
    }
}

class A {
    int num = 1;

    //如果你以后看到一个方法的返回值类型 是一个 类 类型,你就返回该类的一个对象
    public A getA(int num) {
        A a = new A();//new了一个新对象
        a.num = num;//对该对象赋值传入的num
        return a;//返回的是一个新对象
        //return this;该语句返回的是调用该方法的对象a,此时a1.num=1
    }
}
运行结果:1
		100
		org.westos.demo5.A@1540e19d
		org.westos.demo5.A@677327b6
		false
		100

  • 抽象类名作为返回值类型,返回一个该抽象类的子类对象
public class MyTest {
    public static void main(String[] args) {
        Zi zi = new Zi();
        Fu fu = zi.getFu(zi, 109);//返回的是一个父类,用一个父类对象接收返回值,该方法调用后,该父类的num被修改为109
        System.out.println(zi.num); //本类中没有num,去父类中访问,打印109
        System.out.println(fu.num); //打印109
        System.out.println(zi);//打印地址值
        System.out.println(fu);//父类引用指向子类空间,因此两个对象的地址值相同
    }
}

abstract class Fu {
    int num = 10;
}

class Zi extends Fu {

    //如果你以后看到一个方法的返回值类型,要一个抽象类 类型,你就返回一个该抽象类的子类对象
    public Fu getFu(Fu fu, int num) {
        fu.num = num;
        // return new Zi();返回的是一个新的该抽象类的子类对象
        return this;//返回的是传入的子类对象
    }
}
运行结果:109
		109
		org.westos.demo7.Zi@1540e19d
		org.westos.demo7.Zi@1540e19d

  • 接口名作为返回值类型,返回一个实现该接口的子类对象
public class MyTest {
    public static void main(String[] args) {
        MyClass myClass = new MyClass();

        int num=2;

        MyInterface myInterface = get(myClass, num);

        myClass.show(109);//改变了该对象的成员变量值

        System.out.println(myClass.num); //109

        System.out.println(myInterface.NUM);//直接通过类名调用静态变量100

    }
    //如果你以后看到一个方法的返回值类型,要一个接口类型,你就返回该接口的一个子类对象
    public static MyInterface get(MyClass myClass,int num){
        myClass.num=num;//修改了传入的对象的成员变量值
        return myClass;//返回的是传入的
    }

}

interface MyInterface{
    int NUM=100;
    void show(int num);
}

class MyClass implements MyInterface{
    int num=1;
    @Override
    public void show(int num) {
        this.num=num;
    }
}
运行结果:109
		100

02 链式编程

  • 当你调用完一个方法之后,方法的返回值又是一个对象,那么你就可以紧接着打点再去调用该对象的方法。
public class MyTest {
    public static void main(String[] args) {
        Student student = new Student();
        new Student().getStudent(student, 100).show(109);
        System.out.println(student.num); //100
    }
}

class Student {
    int num = 10;

    public Student getStudent(Student stu, int num) {
        stu.num = num;//将传入对象的成员变量值修改了
        return this;//返回调用该方法的对象new student(),而不是传入的对象
    }

    public void show(int num) {
        this.num = num;
    }
}
运行结果:100

03 package关键字

  • 包的概述:就是文件夹,包名必须出现在第一行
  • 包的作用: 用来解决同一个路径下不能存在同名文件的问题(分类管理)
  • 包的划分:按照功能/按照模块
  • 包的定义及注意事项
  • 定义包的格式:package 包名;(多级包用.分开即可)
  • package语句必须是程序的第一条可执行的代码;package语句在一个java文件中只能有一个;如果没有package,默认表示无包名
package org.westos.demo7; //这行代码必须位于第一行

/**
 * @Author: Administrator
 * @CreateTime: 2019-04-14 14:36
 */
public class MyTest {
    public static void main(String[] args) {
        
        }
}

04 不同包下类之间的访问

  • 不同包下的类,进行访问需要导包

05 import关键字

  • 导包格式:import 包名;
  • 注意事项:这种方式导入是到类的名称。
    虽然可以最后写*,但是不建议。
  • 面试题:package,import,class有没有顺序关系
    答:有,package>import>class

06 权限修饰符

Y表示可以访问

本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类)
private Y
默认 Y Y
protected Y Y Y
public Y Y Y Y


07 类及其组成所使用的常见修饰符

A:修饰符:
	权限修饰符:private,默认的,protected,public
	状态修饰符:static,final 
	抽象修饰符:abstract
B:修饰类的关键字:
	权限修饰符:默认修饰符,public
	状态修饰符:final
	抽象修饰符:abstract
	
	用的最多的就是:public
	
C:修饰成员变量的关键字:
	权限修饰符:private,默认的,protected,public
	状态修饰符:static,final
	
	用的最多的就是:private
	
D:修饰构造方法的关键字:
	权限修饰符:private,默认的,protected,public
	
	用的最多的就是:public
	
E:修饰成员方法的关键字:
	权限修饰符:private,默认的,protected,public
	状态修饰符:static,final
	抽象修饰符:abstract
	
	用的最多的就是:public
	
F:除此以外的组合规则:
	成员变量:public static final 
	成员方法:public static 
	         public abstract
			 public final

08 内部类

  • 概述:把类定义在其他类的内部,这个类就被称为内部类。
  • 按照内部类位置分类:成员位置:在成员位置定义的类,被称为成员内部类。
    局部位置:在局部位置定义的类,被称为局部内部类。
public class MyTest {
    public static void main(String[] args) {

    }
}

class B {

    //成员内部类
    class A {

    }

    public void show() {
        //局部内部类
        class C {

        }
    }

}

  • 内部类访问特点
    a:内部类可以直接访问外部类的成员,包括私有。
    b:外部类要访问内部类的成员,必须创建对象。

08.a 成员内部类


  • 在本类中创建成员内部类对象
内部类名 对象名=new 内部类名();
  • 在测试类中创建成员内部类
外部类名.内部类名 对象名=new 外部类名().new 内部类名();

程序示例:

public class MyTest {
    public static void main(String[] args) {
        Outer outer = new Outer();
        System.out.println(outer.num);
        outer.outerShow();
        System.out.println("--------------------------------");
        Outer.Inner inner=new Outer().new Inner();//创建成员内部类的语法
        System.out.println(inner.b);//使用成员内部类的属性和方法
        inner.innerShow();
        System.out.println("---------------");
        outer.method();
    }
}
class Outer {
    int num = 10;
    private int a = 100;
    //定义成员内部类
    class Inner {
        int b = 109;

        public void innerShow() {
            System.out.println("内部类的show方法");
        }
       
        public void innerTest(){
            System.out.println(num); //内部类可以直接访问外部类的成员,包括被private修饰的成员
            System.out.println(a);
            outerShow();
            outerTest();
        }

    }

    public void outerShow() {
        System.out.println("这是外部类的show方法");
    }

    private void outerTest() {
        System.out.println("这是外部类的test方法");
    }
    public void method(){//外部类,想要访问内部类的成员,得创建内部类的对象  
        Inner inner = new Inner();//创建内部类的对象
        System.out.println(inner.b);
        inner.innerShow();

    }

}
运行结果:10
		这是外部类的show方法
		--------------------------------
		109
		内部类的show方法
		---------------
		109
		内部类的show方法

  • 成员内部类的常见修饰符及应用
private 为了保证数据的安全性
static 	为了方便访问数据
注意事项:  a:静态内部类访问的外部类数据必须用静态修饰。
		  b:成员方法可以是静态的也可以是非静态的

程序示例:内部类被private修饰了,外界只能通过外部类提供的公共方法调用内部类成员

public class MyTest {
    public static void main(String[] args) {
        //内部类被private修饰了,外界就不能直接创建内部类对象了
        Wai wai = new Wai();
        wai.waiShow();//外界可以通过外部类提供的方法调用内部类的成员
    }
}


class Wai{
    //private 可以修饰内部类
    private class Nei{
        int num=10;
        public void neiShow(){
            System.out.println("内部类的show方法");
        }

    }

    public void waiShow(){
        Nei nei = new Nei();//外部类提供一个公共方法创建内部类对象,外界通过该方法可以调用内部类的成员
        System.out.println(nei.num);
        nei.neiShow();
    }
}
运行结果:10
		内部类的show方法

程序示例:内部类被static修饰:创建内部类对象的语法发生改变,内部类只能访问外部类的静态成员

public class MyTest {
    public static void main(String[] args) {
        Wai.Nei nei = new Wai.Nei();//内部类被静态修饰后,创建内部类的语法为:外部类名.内部类名 对象名=new 外部类名.内部类名(); 对比非静态语法:外部类名.内部类名 对象名=new 外部类名().new 内部类名();
    }
}

class Wai {
    static int num = 10;
    private int a = 100;

    static class Nei {
        public void neiShow() {
            System.out.println(num);//静态内部类只能访问静态的外部类成员
            waiShow();
        }
    }

    public static void waiShow() {
        System.out.println("外部类的show方法");
    }
}

  • 面试题
class InnerClassTest {
    public static void main(String[] args) {
        Outer.Inner oi = new Outer().new Inner();
        oi.show();
    }
}

class Outer {
    public int num = 10;

    class Inner {
        public int num = 20;

        public void show() {
            int num = 30;
            System.out.println(num); //30
            System.out.println(Inner.this.num); //也可写为this.num访问oi的成员位置20
            System.out.println(new Outer().num); //访问外部类的匿名对象的成员位置10
            System.out.println(Outer.this.num);//访问oi外部类的成员位置10 (注意这种写法)
        }
    }
}

08.b 局部内部类


  • 局部内部类,外界不能直接创建该类对象。其外部类也不能直接创建局部内部类对象,需要通过方法调用。
  • JDK1.8之前,局部内部类,访问外部类的局部变量,局部变量必须被final修饰,否则会报错。JDK1.8默认隐藏final修饰符,建议手动写上final。加上final修饰的目的是延长该局部变量的存活周期。因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。为了让数据还能继续被使用,就用final修饰,这样,在堆内存里面存储的其实是一个常量值。

程序示例:

public class MyTest {
    public static void main(String[] args) {
        //局部内部类,外界不能直接创建其对象
        Outer outer = new Outer();
        //outer.waiShow();//在成员方法内部创建局部内部类对象(局部内部类的位置就在该方法内)
        outer.waiTest();//如果局部内部类所在的成员方法被private修饰,可以通过建立一个公共的方法调用局部内部类所在的成员方法
    }
}
class Outer {
    int num=10;
    private int a=100;
    private void waiShow(){
        final int b=88;//局部内部类访问外部类的局部变量,外部类的局部变量必须加上final修饰
        class Inner{//定义局部内部类
            int c=1;//内部类成员变量
            public void neiShow(){
                System.out.println(num);//内部类可以直接访问外部类的成员,包括私有的成员
                System.out.println(a);
                System.out.println(b);
                System.out.println(c);
            }

        }
        Inner inner = new Inner();
        inner.neiShow();
    }

    public void waiTest(){
       waiShow();
    }

}
运行结果:10
		100
		88
		1

08.c 匿名内部类


  • 匿名内部类,本质上是一个对象,是实现了该接口或继承了该抽象类的子类对象。(一般情况下,抽象类和接口是不可以直接new的,抽象类通过多态和继承new对象,接口通过实现该接口的子类new对象,为了方便传参,采用匿名内部类无需建立子类获取子类类名,便可以直接拿到该抽象类或接口的子类对象,如果想要重复调用,只需给匿名内部类起个名字,就可以实现重复调用)
  • 匿名内部类的语法
new 类名/接口名(){重写方法};

程序示例:

public class MyTest2 {
    public static void main(String[] args) {
        MyInterface myInterface=new BB();//利用多态进行实例化:接口引用指向子类对象
        myInterface.show();
        myInterface.test();
        new MyInterface(){//利用匿名内部类直接调用接口的子类对象成员
            @Override
            public void show() {
                System.out.println("重写了接口中的show方法");
            }

            @Override
            public void test() {
                System.out.println("重写了接口中test方法");
            }
        }.show();

        new MyInterface() {//利用匿名内部类直接调用接口的子类对象成员
            @Override
            public void show() {
                System.out.println("重写了接口中的show方法");
            }

            @Override
            public void test() {
                System.out.println("重写了接口中test方法");
            }
        }.test();

        //给匿名内部类起个名字,用类接收
       MyInterface my= new MyInterface() {
            @Override
            public void show() {
                System.out.println("重写了接口中的show方法");
            }

            @Override
            public void test() {
                System.out.println("重写了接口中test方法");
            }
        };
       //同一个对象,去调用两个方法
       my.show();
       my.test();
    }
}

interface MyInterface{
   public abstract void show();//接口中的方法默认修饰符为public abstract
   public abstract void test();
}

//快捷键ctrl+I 实现接口中的方法
class BB implements MyInterface{
    @Override
    public void show() {
        System.out.println("重写了接口中的show方法");
    }

    @Override
    public void test() {
        System.out.println("重写了接口中的test方法");
    }
}
运行结果:重写了接口中的show方法
		重写了接口中的test方法
		重写了接口中的show方法
		重写了接口中test方法
		重写了接口中的show方法
		重写了接口中test方法

  • 面试题

示例1:

//接口
interface Inter {
    void show();
}

class Outer {
    //补代码
    public static Inter method(){
       Inter in= new Inter() {//匿名内部类直接抓取接口的子类对象,并对该对象命名
            @Override
            public void show() {
                System.out.println("helloworld");
            }
        };
        return in;//返回该对象
    }
}

class OuterDemo {

    public static void main(String[] args) {

        //要求在控制台输出”HelloWorld”
        Outer.method().show();//分析通过outer调用method,method方法需要返回一个对象,继续调用show,而接口中有show方法,因此需要在method中返回一个接口的子类对象,采用匿名内部类最合适。
    }
}

示例2:

public class PersonTest {
    public static void main(String[] args) {
        //如何调用PersonDemo中的method方法呢?
        //补充代码
        PersonDemo pd=new PersonDemo();
        pd.method(new Person(){

            @Override
            public void show() {
                System.out.println("Person类的show方法");
            }
        });
    }
}
abstract class Person {
    public abstract void show();
}

class PersonDemo {
    public void method(Person p) {
        p.show();
    }
}

示例3:匿名内部类中this关键字

interface Inter {
		public static final int a = 23 ;
	}
	
	public class Test {

		public static void main(String[] args) {
			new Inter() {
				public void show() {
				// 这个this表示的是匿名内部类的这个对象
					System.out.println(this.a);
				}
			}.show();
		}
	}
运行结果:23

09 类中定义内部接口

public class MyTest {
    public static void main(String[] args) {
        //间接方式
        Outer outer = new Outer();
        outer.waiShow();//通过waiShow方法调用公共的内部接口属性
        outer.waiShow1();//通过waiShow1方法调用私有的内部接口属性
        //直接方式
        //注意这种方式只能抓取公共的内部接口或抽象类的子类对象,不能抓取私有的。
       Outer.Inner inner= new Outer.Inner() {//通过匿名内部类直接抓取公共的内部接口对象。
            @Override
            public void show() {
                System.out.println("1.重写了接口中的show方法");
            }
        };
       inner.show();//给匿名内部类起名后可以重复调用该类成员 
       inner.show();
       
    }

}


     class Outer {
        //公共的成员内部接口
        interface Inner{
            public abstract void show();
        }
        //私有的成员内部接口
        private interface Inner1 {
            public abstract void show1();
        }

        public void waiShow() {//通过waiShow方法调用公共内部接口中show方法
            new Inner() {
                @Override
                public void show() {
                    System.out.println("重写了接口Inner中的show方法");
                }
            }.show();

        }
        public void waiShow1(){//通过waiShow1方法调用私有内部接口的show1方法
            new Inner1() {
                @Override
                public void show1() {
                    System.out.println("重写了接口Inner1中的show1方法");
                }
            }.show1();
        }
    }