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();
}
}