1:形式参数和返回值的问题(理解)
(1)形式参数:
类名:需要该类的对象,总之需要类变量的都是需要其实例化的对象 特别例子://匿名对象用法 new StudentDemo().method(new Student());//
抽象类名:需要该类的子类对象,抽象类本身不能实例化,抽象类有构造方法,但不能用作实例化调用,仅仅用于子类访问父类数据的初始化,继承父类的子类方式有两种(1.抽象类继承抽象类,此时不能实例化,但也不用重写抽象方法;2.具体类继承抽象类,重写抽象方法,使其能进行实例化,使其在堆内存区有一份对象数据,把引用地址赋值给抽象类的引用类型变量完成实例化)
接口名:需要该接口的实现类对象,接口本身不能实例化,因为没有构造方法,实现接口的子类方式有两种(1.抽象类实现接口,此时不能实例化,但也不用重写抽象方法;2.具体类实现对象,重写接口抽象方法,使其能进行实例化,使其在堆内存区有一份对象数据,把引用地址赋值给接口的引用类型变量完成实例化)
例子:
类作为形式参数:
class Student {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class StudentDemo {
public void method(Student s) { //ss; ss = new Student(); Student s = new Student();
s.study();
}
}
class StudentTest {
public static void main(String[] args) {
//需求:我要测试Student类的study()方法
Student s = new Student();
s.study();
System.out.println("----------------");
//需求2:我要测试StudentDemo类中的method()方法
StudentDemo sd = new StudentDemo();
Student ss = new Student();
sd.method(ss);
System.out.println("----------------");
//匿名对象用法
new StudentDemo().method(new Student());
}
}
抽象类作为形式参数:
abstract class Person {
public abstract void study();
}
class PersonDemo {
public void method(Person p) {//p; p = new Student(); Person p = new Student(); //多态
p.study();
}
}
//定义一个具体的学生类
class Student extends Person {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class PersonTest {
public static void main(String[] args) {
//目前是没有办法的使用的
//因为抽象类没有对应的具体类
//那么,我们就应该先定义一个具体类
//需求:我要使用PersonDemo类中的method()方法
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
}
}
接口作为形式参数:
interface Love {
public abstract void love();
}
class LoveDemo {
public void method(Love l) { //l; l = new Teacher(); Love l = new Teacher(); 多态
l.love();
}
}
//定义具体类实现接口
class Teacher implements Love {
public void love() {
System.out.println("老师爱学生,爱Java,爱林青霞");
}
}
class TeacherTest {
public static void main(String[] args) {
//需求:我要测试LoveDemo类中的love()方法
LoveDemo ld = new LoveDemo();
Love l = new Teacher();
ld.method(l);
}
}
(2)返回值类型:
类名:返回的是该类的对象
抽象类名:返回的是该类的子类对象
接口名:返回的是该接口的实现类的对象
类,抽象类,接口作为返回值的例子:
类做返回:
class Student {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class StudentDemo {
public Student getStudent() {
//Student s = new Student();
//Student ss = s;
//Student s = new Student();
//return s;
return new Student();
}
}
class StudentTest2 {
public static void main(String[] args) {
//需求:我要使用Student类中的study()方法
//但是,这一次我的要求是,不要直接创建Student的对象
//让你使用StudentDemo帮你创建对象
StudentDemo sd = new StudentDemo();
Student s = sd.getStudent(); //new Student(); Student s = new Student();
s.study();
}
}
抽象类做返回:
abstract class Person {
public abstract void study();
}
class PersonDemo {
public Person getPerson() {
//Person p = new Student();
//return p;
return new Student();
}
}
class Student extends Person {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class PersonTest2 {
public static void main(String[] args) {
//需求:我要测试Person类中的study()方法
PersonDemo pd = new PersonDemo();
Person p = pd.getPerson(); //new Student(); Person p = new Student(); 多态
p.study();
}
}
接口做返回:
interface Love {
public abstract void love();
}
class LoveDemo {
public Love getLove() {
//Love l = new Teacher();
//return l;
return new Teacher();
}
}
//定义具体类实现接口
class Teacher implements Love {
public void love() {
System.out.println("老师爱学生,爱Java,爱林青霞");
}
}
class TeacherTest2 {
public static void main(String[] args) {
//如何测试呢?
LoveDemo ld = new LoveDemo();
Love l = ld.getLove(); //new Teacher(); Love l = new Teacher(); 多态
l.love();
}
}
(3)链式编程
对象.方法1().方法2().......方法n();
这种用法:其实在方法1()调用完毕后,应该一个对象;
方法2()调用完毕后,应该返回一个对象。
方法n()调用完毕后,可能是对象,也可以不是对象。
例子:
/*
链式编程。
每次调用完毕方法后,返回的是一个对象。
*/
class Student {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class StudentDemo {
public Student getStudent() {
return new Student();
}
}
class StudentTest3 {
public static void main(String[] args) {
//如何调用的呢?
StudentDemo sd = new StudentDemo();
//Student s = sd.getStudent();
//s.study();
//大家注意了
sd.getStudent().study();
}
}
2:包(理解)
(1)其实就是文件夹
(2)作用:
A:区分同名的类
B:对类进行分类管理
a:按照功能分 (CRUD四个功能,四个包,各自底下有学生添加,学生删除老师添加,老师删除等)
b:按照模块分(老师包,学生包,每个包各自含自己的CRUD功能)
(3)包的定义(掌握)
package 包名;
多级包用"."分开即可。
(4)注意事项:(掌握)
A:package语句必须在文件中的第一条有效语句
B:在一个java文件中,只能有一个package
C:如果没有package,默认就是无包名
(5)带包的编译和运行
A:手动式
a.编写一个带包的java文件
b.通过javac命令编译该java文件
c.手动创建包名
d.把b步骤的class文件放到C步骤的最底层包
e:回到和包根目录在同一目录的地方,然后运行,记住带包运行。java cn.itcast.HelloWorld
B:自动式(掌握)
javac -d . HelloWorld.java (-d:创建目录,"."表示在本路径下创建)
1.编写一个带包的java文件
2.javac编译的时候带上-d即可
javac -d . HelloWorld.java
3.回到和包根目录在同一目录的地方,然后运行,记住带包运行java cn.itcast.HelloWorld
不同包下类之间的访问:先编译引入包的java文件,再编译执行包下的java文件,再带包运行
3:导包(掌握)
(1)我们多次使用一个带包的类,非常的麻烦,这个时候,Java就提供了一个关键字import。
(2)格式:
import 包名...类名; //这种方式导入是到类的级别
另一种:
import 包名...*;(不建议)
(3)package,import,class的顺序
package > import > class
package:只能有一个
import:可以有多个
class:可以有多个,以后建议是一个
4:权限修饰符(掌握)
(1)权限修饰符
本类 同一个包下(包含子类与无关类) 不同包下的子类 不同包下的无关类
private Y
默认 Y Y
protected Y Y Y
public Y Y Y Y
(2)这四种权限修饰符在任意时刻只能出现一种。
public class Demo {}
5:常见的修饰符(理解)
(1)分类:
权限修饰符:private,默认,protected,public
状态修饰符:static,final
抽象修饰符:abstract
(2)常见的类及其组成的修饰
修饰符:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
类:
权限修饰符:默认修饰符,public
状态修饰符:final
抽象修饰符:abstract
用的最多的就是:public
//此处不允许使用修饰符private
//此处不允许使用修饰符protected
//此处不允许使用修饰符static
成员变量:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
用的最多的就是:private
构造方法:
权限修饰符:private,默认的,protected,public
用的最多的就是:public
成员方法:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
用的最多的就是:public
除此以外的组合规则:
成员变量:public static final
成员方法:public static
public abstract
public final
(3)另外比较常见的:
public static final int X = 10;
public static void show() {}
public final void show() {}
public abstract void show();
6:内部类(理解)
(1)把类定义在另一个类的内部,该类就被称为内部类。
举例:把类B定义在类A中,类B就被称为内部类。
(2)内部类的访问规则
A:可以直接访问外部类的成员,包括私有
B:外部类要想访问内部类成员,必须创建对象
(3)内部类的分类 (注意:类与类是平级关系)
A:成员内部类:在成员位置定义的类,被称为成员内部类
B:局部内部类:在局部位置定义的类,被称为局部内部类
(4)成员内部类 (外部类没有static作为修饰,而内部类则可以用static修饰,因为内部类把他看做外部类的成员来看待,成员是可以用静态修饰的)
A:private 为了保证数据的安全性 身体类(包含心脏类,肝脏类,肺类等,这些都用私有内部类)
B:static 为了让数据访问的方便性 ,内部类用静态修饰是因为内部类可以看出是外部类的成员,一般使用static修饰内部类的话,会用public作为访问修饰符,因为已经在类加载是加载了,算是顶层类,一般这样用不用构造方法,直接类名加方法就好了,所以,一般公用的才使用public
被静态修饰的成员内部类只能访问外部类的静态成员
内部类方法被静态修饰后的方法:1.静态方法2.非静态方法
成员内部类不是静态的:
外部类名.内部类名 对象名 = new 外部类名().new 内部类名(); 例子:Outer.Inner oi = new Outer().new Inner();
成员内部类是静态的:
外部类名.内部类名 对象名 = new 外部类名.内部类名(); 例子:Outer.Inner oi = new Outer.Inner();
(5)成员内部类的面试题(填空)
/*
面试题:
要求请填空分别输出30,20,10。
注意:
1:内部类和外部类没有继承关系。
2:通过外部类名限定this对象
Outer.this
*/
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num); //就近原则下的num
System.out.println(this.num); //本类下的成员变量num
//System.out.println(new Outer().num); //这句是可以的,创建一个匿名对象调用变量,但不是最简单,最简单在下面
System.out.println(Outer.this.num); //利用Outer.this,限制this的范围,来访问Outer下的num
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
(6)局部内部类(这个点很容易被忽视)
可以直接访问外部类的成员
可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
局部内部类访问局部变量的注意事项:
A:局部内部类访问局部变量必须加final修饰。
B:为什么呢?
因为局部变量是随着方法的调用而调用,随着调用完毕而消失。而堆内存的数据并不会立即消失。
所以,堆内存还是用该变量,而该变量已经没有了。
为了让该值还存在,就加final修饰。
通过反编译工具我们看到了,加入final后,这个变量就成了常量,堆内存直接存储的是值,而不是变量名。
局部内部类例子,面试题:
/*
局部内部类
A:可以直接访问外部类的成员
B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
面试题:
局部内部类访问局部变量的注意事项?
A:局部内部类访问局部变量必须用final修饰
B:为什么呢?
局部变量是随着方法的调用而调用,随着调用完毕而消失。
而堆内存的内容并不会立即消失。所以,我们加final修饰。
加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
我在内存中存储的是数据20,所以,我还是有数据在使用。
*/
class Outer {
private int num = 10;
public void method() {
//int num2 = 20; //jdk报错,说明一定要final作为局部变量的修饰
final int num2 = 20;//对的
class Inner {
public void show() {
System.out.println(num);
//从内部类中访问本地变量num2; 需要被声明为最终类型,可以利用反编译穿软件看看,是否直接变为20,连变量名都消失了
System.out.println(num2);//20
}
}
//System.out.println(num2);
Inner i = new Inner();
i.show();
}
}
class InnerClassDemo5 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
(7)匿名内部类(掌握)
A:其实是局部内部类的简化形式
B:前提
存在一个类或者接口,这里的类可以是具体类也可以是抽象类
C:格式:
new 类名或者接口名() {
重写方法;
}
D:本质:
其实是继承该类(具体类对象)或者实现接口的子类(实现类)匿名对象
E:好处:在使用匿名对象或匿名内部类时,都是一次定义,一次使用就不会用了,所以不用创建引用变量指向对象引用地址,匿名的使用能让jvm的垃圾回收机制快点收回内存,因为它没有被栈的变量所指向,所以回收速度最快。
弊端:只能使用一次
(8)匿名内部类在开发中的使用
我们在开发的时候,会看到抽象类,或者接口作为参数。
而这个时候,我们知道实际需要的是一个子类对象。
如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。
例子:
/*
匿名内部类在开发中的使用
*/
interface Person {
public abstract void study();
}
class PersonDemo {
//接口名作为形式参数
//其实这里需要的不是接口,而是该接口的实现类的对象
public void method(Person p) {
p.study();
}
}
//实现类
class Student implements Person {
public void study() {
System.out.println("好好学习,天天向上");
}
}
class InnerClassTest2 {
public static void main(String[] args) {
//测试
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
System.out.println("--------------------");
//匿名内部类在开发中的使用
//匿名内部类的本质是继承类或者实现了接口的子类匿名对象
pd.method(new Person(){
public void study() {
System.out.println("好好学习,天天向上");
}
});
}
}
(9)匿名内部类的面试题(补齐代码)
/*
匿名内部类面试题:
按照要求,补齐代码
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
*/
interface Inter {
void show();
//public abstract
}
class Outer {
//补齐代码
public static Inter method() {
//子类对象 -- 子类匿名对象
return new Inter() {
public void show() {
System.out.println("HelloWorld");
}
};
}
}
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
/*
1:Outer.method()可以看出method()应该是Outer中的一个静态方法。
2:Outer.method().show()可以看出method()方法的返回值是一个对象。
又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。
*/
}
}