当你以后看到一个方法的形参要一个 类 类型,你就传递一个该类的对象。
代码如下及分析:
public class MyTest { public static void main(String[] args) { Student student = new Student(); show(new Student(), 20); student.setNum(40); System.out.println(student.num); } public static void show(Student student, int num) { student.num = num; } } class Student { int num = 100; public void setNum(int num) { this.num = num; } }
分析:从psvm入手,先new了一个Student,开辟了一个内存空间,紧接着走到了show方法,调用showf方法,把num=20赋给void show里的student.num,接着student.setNum(40)将其传给class Student里的int num里的num原本是100,现在变成40并赋给this.num,返回给输出的sout里的student.num。
当你以后看到一个方法的形参要一个抽象类 类型,你就传递一个该抽象类的子类对象。
代码如下:
public class MyTest { public static void main(String[] args) { BB bb = new BB(); show(bb, 50); System.out.println(bb.num); // bb.aa(); } public static void show(AA aa, int num) { aa.num = num; } } abstract class AA { int num = 100; public abstract void aa(); } class BB extends AA { int num = 20; @Override public void aa() { System.out.println(super.num); } }
分析:从psvm入手,先new了一个BB,开辟了内存空间,此时的BB是AA的子类,先对父类初始化得到num=100,再对子类进行初始化得到num=20,回到psvm中的show,将bb和num=50传到static void里的show方法,得此时aa.num=50,由于开始是num由0到100再到20,所以输出bb.num=20,再用bb调用aa,由于aa在子类中重写并通过关键字super调用父类中的aa(),但被改写为num=50,故输出50。
当你以后看到一个方法的形参要一个接口 类型 ,你就传递一个该接口的子类对象。
代码如下:
public class MyTest { public static void main(String[] args) { MyClass myClass = new MyClass(); show(myClass); myClass.setNum(500); System.out.println(myClass.num); //2.500 System.out.println(MyInterface.num); //3.100 } public static void show(MyInterface myInterface) { System.out.println(myInterface.num); //1.100 } } interface MyInterface { public static final int num = 100; void aa(); } class MyClass implements MyInterface { int num = 20; public void setNum(int num) { this.num = num; } @Override public void aa() { System.out.println(num); } }
分析:
1.由于在接口中定义的静态常量不可被调整,故输出100;
2.给Myclass中的num本身初始化为20但经过setNum(500)之后变为500;
3.同理1输出100。
当你以后看到一个方法的返回值类型,是一个类 类型,你就返回一个该类的对象。
代码如下:
public class MyTest { public static void main(String[] args) { Student student = getStudent(); student.setNum(80); int num = student.getNum(); System.out.println(num); } public static Student getStudent() { Student student = new Student(); student.num = 50; return new Student(); } } class Student { int num = 20; public void setNum(int num) { this.num = num; } public int getNum() { return num; } }
**分析:**已知返回值为new Student(),属于一个类类型,那么返回的应该是其子类对象,而子类对象原本是初始化20,又经psvm的setNum(80)改为了80,故最后输出80。
当你以后看到一个方法的返回值类型是一个抽象类 类型,你就返回一个该抽象类的子类对象。
代码如下:
public class MyTest { public static void main(String[] args) { CC cc = test(); cc.num = 500; cc.cc(); //1.120 System.out.println(cc.num);//2.500 } public static CC test() { MyClass myClass = new MyClass(); myClass.num = 120; return myClass; } } abstract class CC { int num = 20; public abstract void cc(); } class MyClass extends CC { int num = 10; @Override public void cc() { System.out.println(num); } }
当你以后看到一个方法的返回值类型是一个接口 类型,你就返回一个该接口的子类对象。
代码如下:
public class MyTest { public static void main(String[] args) { Myinterface myinterface = test(8); System.out.println(myinterface.num);//100 System.out.println(Myinterface.num); //100 BB bb = (BB) myinterface; System.out.println(bb.num); //8 } public static Myinterface test(int num) { BB bb = new BB(); bb.num = num; return bb; } } interface Myinterface { int num = 100; public abstract void show(int num); } class BB implements Myinterface { int num = 20; @Override public void show(int num) { System.out.println(num); } }
代码如下及分析:
public class MyTest { public static void main(String[] args) { //链式编程风格 //当你调用完一个方法,这个方法的返回值是个对象,那么你可以继续打点,调用该对象中的方法。 int num = new Student().getStudent(new Student(), 800).getStudent(new Student(), 9000).getNum(); System.out.println(num); /* Student student = new Student(); Student student1 = student.getStudent(new Student(), 800); Student student2 = student1.getStudent(new Student(), 9000); int num1 = student2.getNum(); System.out.println(num1);*/ } } class Student { int num = 10; public int getNum() { return num; } public void setNum(int num) { this.num = num; } public Student getStudent(Student student, int num) { student.num = num; Student student1 = new Student(); student1.setNum(900); return student; } }
1.包的概述: 文件夹;
2.包的作用: 用来解决同一个路径下不能存在同名文件的问题(分类管理);
3.包的划分:按照功能;按照模块
1.定义包的格式
package 包名;多级包用,分开即可
2.定义包的注意事项
(1).package语句必须是程序的第一条可执行的代码;
(2).package语句在一个java文件中只能有一个;
(3).如果没有package,默认表示无包名。
不同包下类之间的访问
定义两个类:Demo,Test。
Demo 求和方法(sum)
Test 测试方法(main)
1.导包的概述
不同包下的类之间的访问,我们发现,每次使用不同包下的类的时候,都需要加包的全路径。比较麻烦。这个时候,java就提供了导包的功能
2.导包格式
import 包名;
注意:
这种方式导入是到类的名称。
虽然可以最后写*,但是不建议。
3.package,import,class有没有顺序关系(面试题)
1.四种权限修饰符: private(私有的) , 默认 , protected(受保护的) , public(公共的)
2.结论
本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类) private Y 默认 Y Y protected Y Y Y public Y Y Y Y
1.修饰符: 权限修饰符:private,默认的,protected,public 状态修饰符:static,final 抽象修饰符:abstract 2.修饰类的关键字: 权限修饰符:默认修饰符,public 状态修饰符:final 抽象修饰符:abstract 用的最多的就是:public 3.修饰成员变量的关键字: 权限修饰符:private,默认的,protected,public 状态修饰符:static,final 用的最多的就是:private 4.修饰构造方法的关键字: 权限修饰符:private,默认的,protected,public 用的最多的就是:public 5.修饰成员方法的关键字: 权限修饰符:private,默认的,protected,public 状态修饰符:static,final 抽象修饰符:abstract 用的最多的就是:public 6.除此以外的组合规则: 成员变量:public static final 成员方法:public static public abstract public final
1.内部类概述:把类定义在其他类的内部,这个类就被称为内部类。
举例:在类A中定义了一个类B,类B就是内部类。
2.内部类访问特点
(1).内部类可以直接访问外部类的成员,包括私有。
(2).外部类要访问内部类的成员,必须创建对象。
1.按照内部类位置分类
成员位置:在成员位置定义的类,被称为成员内部类。
局部位置:在局部位置定义的类,被称为局部内部类。
2.成员内部类
换句话说就是如何在测试类中直接访问内部类的成员?
格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象。
1.成员内部类的修饰符:
private 为了保证数据的安全性
static 为了方便访问数据
注意事项: 1.静态内部类访问的外部类数据必须用静态修饰。
2.成员方法可以是静态的也可以是非静态的
2.成员内部类被静态修饰后的访问方式是:
格式: 外部类名.内部类名 对象名 = new 外部类名.内部类名();
要求:使用已知的变量,在控制台输出30,20,10。 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(this.num); //20 System.out.println(Outer.this.num); //10 } } } class InnerClassTest { public static void main(String[] args) { Outer.Inner oi = new Outer().new Inner(); oi.show(); } }
1.可以直接访问外部类的成员
2.可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
3.局部内部类访问局部变量必须用final修饰
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。为了让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。JDK1.8之后,final会默认加上,你不用手动去加,但是你要知道。
1.匿名内部类:就是局部内部类的简化写法。
2.前提:存在一个类或者接口;这里的类可以是具体类也可以是抽象类。
3.格式:
new 类名或者接口名(){
重写方法;
} ;
4.本质是一个继承了该类或者实现了该接口的子类匿名对象。
nterface 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);//23 } }.show(); } }
需求:要求在控制台输出”HelloWorld!” interface Inter { void show(); } class Outer { public static Inter method(){ return new Inter(){ @Override public void show() { System.out.println("Hello World!"); } }; } } class OuterDemo { public static void main(String[] args) { Outer.method().show(); } }