1.类名作为形式参数
当你以后看到一个方法的形参要一个 类 类型,你就传递一个该类的对象
public class MyTest {
public static void main(String[] args) {
//基本类型作为参数传递:属于值传递,传递的是值,形参的改变,不影响实参。
//引用类型作为参数传递:属于引用传递,传递的是地址值,形参的改变会影响实参。
//当你以后看到一个方法的形参,要一个类 类型,,你就传递一个该类的对象。
Student student = new Student();
student.num=80;
set(student);
student.show(55);
System.out.println(student.num);//55
}
public static void set(Student student){
student.num=20;
}
}
class Student {
int num=120;
public void show(int num){
this.num=num;
}
}
2.抽象类名作为形式参数
当你以后看到一个方法的形参要一个抽象类 类型,你就传递一个该抽象类的子类对象。
public class MyTest {
public static void main(String[] args) {
//当你以后看到一个方法的形参要一个抽象类 类型,你就传递该抽象类的子类对象。
B b = new B();
test(b);
System.out.println(b.num);//90
}
public static void test(A a){ //A a=b 多态
a.num=100; //多态的形式访问成员变量,编译看左边,运行也看左边
}
}
abstract class A{
int num=20;
public abstract void show(int a);
}
class B extends A{
int num=90;
@Override
public void show(int a) {
this.num=a;
}
}
3.接口名作为形式参数
当你以后看到一个方法的形参要一个接口 类型 ,你就传递一个该接口的子类对象。
public class MyTest {
public static void main(String[] args) {
//当你以后看到一个方法的形参,要一个接口类型,你就传递一个接口的子类对象。
B b = new B();
test(b);
b.show(50);
System.out.println(b.num); //50
System.out.println(MyInterface.num);//200
}
public static void test(MyInterface myInterface) { //MyInterface myInterface=b //多态
System.out.println(myInterface.num);//200
}
}
interface MyInterface {
public static final int num = 200;
public abstract void show(int a);
}
class B implements MyInterface {
int num = 30;
@Override
public void show(int a) {
this.num = a;
}
}
4.类名作为返回值类型
当你以后看到一个方法的返回值类型,是一个类 类型,你就返回一个该类的对象。
public class MyTest {
public static void main(String[] args) {
Student student = getStudent(10);
student.num = 555;
Student s2= student.test(89);
System.out.println(student.num); //89
System.out.println(s2.num); //89
System.out.println(s2==student);
}
//如果你以后看到一个方法的返回值类型,是一个类 类型,你就返回该类的对象。
public static Student getStudent(int num) {
Student student = new Student();
student.num = num;
return student;
}
}
class Student {
int num = 20;
public Student test(int a) {
this.num = a;
return this; //this 代表一个该类的引用,哪个对象调用这个方法,方法中的this 就代表谁
}
}
5.抽象类名作为返回值类型
当你以后看到一个方法的返回值类型是一个抽象类 类型,你就返回一个该抽象类的子类对象。
public class MyTest {
public static void main(String[] args) {
AA aa = test(120); //AA aa=bb
System.out.println(aa.num); //20
aa.show();
}
//当你以后看到一个方法的返回值类型要一个 抽象类 类型,返回该类的子类对象
public static AA test(int a) {
BB bb = new BB();
bb.num = a;
return bb;
}
}
abstract class AA {
int num = 20;
public abstract void show();
}
class BB extends AA {
int num = 30;
@Override
public void show() {
System.out.println(num); //120
}
}
6.接口名作为返回值类型
当你以后看到一个方法的返回值类型是一个接口 类型,你就返回一个该接口的子类对象
public class MyTest {
public static void main(String[] args) {
MyInterface anInterface = getInterface(); // MyInterface anInterface =aa
System.out.println(anInterface.num);//20
//向下转型
AA aa= (AA) anInterface;
System.out.println(aa.num);//90
}
//当你以后看到一个方法的,返回值类型是一个 接口类型,你就返回该接口的子类对象。
public static MyInterface getInterface(){
AA aa = new AA();
aa.num=90;
return aa;
}
}
interface MyInterface{
public static final int num=20;
}
class AA implements MyInterface{
int num=100;
}
7.链式编程
public class MyTest {
public static void main(String[] args) {
//Student student = new Student();
// Student student1 = student.getStudent(student, 30);
// int num = student1.getNum();
/* Student student = new Student();
Student student1 = student.getStudent(new Student(), 20);
int num1 = student1.getNum();
System.out.println(num1); //20*/
//链式编程:当你调用完一个方法后,这个方法会返回一个对象,你就可以紧接着打点,继续调用该对象的方法。
// int num = new Student().getStudent(new Student(), 20).getNum();
// System.out.println(num);//200
int num1 = new Student().getStudent(new Student(), 20).getStudent(new Student(), 60).getStudent(new Student(),90).getNum();
System.out.println(num1);//200,因为返回值是student;
}
}
class Student{
int num=200;
public Student getStudent(Student student,int a){
Student s1 = new Student();
s1.num=a;
return student;
}
public int getNum(){
return this.num;
}
}
8.package关键字的概述及作用
1.包的概述: 就是文件夹
2.包的作用: 用来解决同一个路径下不能存在同名文件的问题(分类管理)
3.包的划分:
按照功能
按照模块
9.包的定义及注意事项
1.定义包的格式
package 包名;
多级包用.分开即可
2.定义包的注意事项
A:package语句必须是程序的第一条可执行的代码
B:package语句在一个java文件中只能有一个
C:如果没有package,默认表示无包名
10.import关键字的概述和使用
1.导包的概述
不同包下的类之间的访问,我们发现,每次使用不同包下的类的时候,都需要加包的全路径。比较麻烦。这个时候,java就提供了导包的功能
2.:导包格式
import 包名;
注意:
这种方式导入是到类的名称。
虽然可以最后写*,但是不建议。
3.package,import,class有没有顺序关系 有,1.package 2.import 3.class
同一包下使用不同类时,不需要导包。
要使用不同包下得MyPay类,就需要导包
12.四种权限修饰符的测试
1.四种权限修饰符: private(私有的) , 默认 , protected(受保护的) , public(公共的)
2.结论
本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类)
private Y
默认 Y Y
protected Y Y Y
public Y Y Y Y
public>protected>默认>private
13.类及其组成所使用的常见修饰符
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
14.内部类概述和访问特点
1.内部类概述: 把类定义在其他类的内部,这个类就被称为内部类。
举例:在类A中定义了一个类B,类B就是内部类。
public class MyTest {
public static void main(String[] args) {
//内部类:将一个类A定义到另一个类B 的内部,类A就是内部类,类B叫做外部类
//根据内部类定义的位置不同可以分为:成员内部类和局部内部类
// 成员内部类:将内部类定义到外部类的成员位置
//局部内部类:将内部类定义到外部类的局部位置(方法内)
}
}
class Wai{
//成员内部类
class Nei {
}
public void show(){
//局部内部类
class C{
}
}
}
15.内部类分类及成员内部类的直接使用
1.按照内部类位置分类
成员位置:在成员位置定义的类,被称为成员内部类。
局部位置:在局部位置定义的类,被称为局部内部类。
2.成员内部类
如何在测试类中直接访问内部类的成员。
格式: 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
1.内部类访问特点
a:内部类可以直接访问外部类的成员,包括私有。
b:外部类要访问内部类的成员,必须创建对象。
外部类:
public class Wai {
int num=20;
private double a=100;
class Nei{
int b=40;
public void neiShow(){
System.out.println("nei show"+b);
System.out.println(num);
System.out.println(a);
waiShow();
waiShow2();
}
public void neiTest(){
System.out.println("abc");
}
}
public void waiShow(){
System.out.println("外部类的show");
}
private void waiShow2() {
System.out.println("外部类的show");
}
public void hehe(){
//neiTest()
//外部类要访问内部类的成员,要创建内部类的对象。
Nei nei = new Nei();
nei.neiTest();
}
}
测试类:
public class MyTest {
public static void main(String[] args) {
//怎么调用成员内部类的属性和方法。
//创建成员内部类的对象
// 如何在测试类中直接访问内部类的成员。
// 格式:
// 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Wai.Nei nei=new Wai().new Nei();
nei.neiShow();
System.out.println(nei.b);
//内部类的特点:可以直接访问外部类的成员,包括私有成员。
}
}
16.成员内部类的常见修饰符及应用
1.成员内部类的修饰符:
private 为了保证数据的安全性
static 为了方便访问数据
注意事项: a:静态内部类访问的外部类数据必须用静态修饰。
b: 成员方法可以是静态的也可以是非静态的
2.成员内部类被静态修饰后的访问方式是:
格式: 外部类名.内部类名 对象名 = new 外部类名.内部类名();
用static修饰内部类:
public class MyTest {
public static void main(String[] args) {
// Outer.Inner inner = new Outer().new Inner();
// 静态的成员内部类,创建对象的语法是这样的
Outer.Inner inner=new Outer.Inner();
}
}
class Outer{
static int num=200;
//静态可以修饰内部类。
//静态内部类,只能访问外部类的静态成员,非静态成员无法访问。
static class Inner{
int a=20;
static int b=200;
public void show(){
System.out.println(num);
haha();
}
public static void hehe(){
System.out.println(num);
}
}
public static void haha(){
}
}
用private修饰内部类时,间接调用内部方法:
public class MyTest {
public static void main(String[] args) {
//内部类一旦被私有,外键就无法创建其对象了。
// Wai.Nei nei = new Wai().new Nei();
Wai wai = new Wai();
wai.haha();
}
}
class Wai {
//内部类可以私有
private class Nei {
public void neiShow(){
System.out.println("nei show");
}
}
public void haha(){
Nei nei = new Nei();
nei.neiShow();
}
}
17.成员内部类的面试题
面试题
要求:使用已知的变量,在控制台输出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; 30
System.out.println(num); // this.num 20
System.out.println(num); //new Outer().num 10
//在内部类的方法中,访问外部类的成员可以此语法。
System.out.println(Outer.this.num); //10}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
18.局部内部类访问局部变量的问题
1.可以直接访问外部类的成员
2.可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
3.局部内部类访问局部变量必须用final修饰
为什么呢?
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。
为了让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。
JDK1.8之后,final会默认加上,你不用手动去加,但是你要知道
在测试类中间接访问局部内部类方法:
public class MyTest {
public static void main(String[] args) {
//内部类可以直接访问外部类的成员,包括私有成员。
//局部内部类,在外界没有直接创建其对象的语法。
Wai wai = new Wai();
wai.show();
}
}
class Wai{
int a=10;
private int num=100;
public void show(){
//局部内部类型
class Nei{
public void neiShow(){
System.out.println(a);
System.out.println(num);
}
}
//创建局部内部类的对象
Nei nei = new Nei();
nei.neiShow();
}
public void hehe(){
}
}
局部内部类访问外部类局部方法内得局部变量加final变为常量:
public class MyTest {
}
class Outer{
int num=100;
public void show(final int b){
/*
*
* C:局部内部类访问局部变量必须用final修饰为什么呢?
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。
为了让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。
JDK1.8之后,final会默认加上,你不用手动去加,但是你要知道
* */
//局部变量
final int a = 10;
class Inner{
//局部内部类,访问外部类的局部变量时,这个局部变量要加final修饰使其成为一个常量 JDK1.8之后,默认就加上了。
public void hehe(){
System.out.println(num);
System.out.println(a);
System.out.println(b);
}
}
}
}
19.匿名内部类的格式和理解
1.匿名内部类: 就是局部内部类的简化写法。
2.前提: 存在一个类或者接口;这里的类可以是具体类也可以是抽象类。
3.格式:
new 类名或者接口名(){
重写方法;
} ;
4.本质是什么呢?
是一个继承了该类或者实现了该接口的子类匿名对象。
想要一个抽象类得子类对象:
public class MyTest {
public static void main(String[] args) {
//匿名内部类:他是局部内部类的一种简写方式,
//匿名内部类,本质上是一个对象,是谁的对象呢?是实现了该接口或继承了该抽象类或普通类的子类对象。
//BB bb = new BB();
//bb.aa();
/*
new 类名或接口名(){
重写接口或类中的方法
};
*/
new AA() {
@Override
public void aa() {
System.out.println("我重写了aa方法");
}
@Override
public void bb() {
System.out.println("ccccccccccccccccccccc");
}
};
new AA() {
@Override
public void aa() {
System.out.println("我重写了aa方法22222");
}
@Override
public void bb() {
System.out.println("eeeeeeeeeeeeeeeeeeeeeeeeeee");
}
}.aa();
//多态
AA myaa = new AA() {
@Override
public void aa() {
System.out.println("我重写了aa方法2222244444444444444444444444");
}
@Override
public void bb() {
System.out.println("eeeeeeeeee3333333333333333333eeeeeeeeeeeeeeeee");
}
};
myaa.aa();
myaa.bb();
}
}
abstract class AA {
public abstract void aa();
public abstract void bb();
}
/*
class BB extends AA{
@Override
public void aa() {
}
}
*/
想要一个接口得子类对象:
public class MyTest2 {
public static void main(String[] args) {
// CC cc = new CC();
// cc.test();
//我只想要一个接口的子类对象
new MyInterface() {
@Override
public void test() {
System.out.println("cccccccccccccccccc");
}
@Override
public void aa() {
System.out.println("aaaaaaaaaaaaaaaaaaaaa");
}
}.test();
new MyInterface() {
@Override
public void test() {
System.out.println("cccccccccccccccccccdeedfefefef");
}
@Override
public void aa() {
System.out.println("ccccccccccccccccccccccccccererer");
}
}.aa();
MyInterface myInterface = new MyInterface() {
@Override
public void test() {
System.out.println("cccccccccccccccccccdeedfefefef");
}
@Override
public void aa() {
System.out.println("ccccccccccccccccccccccccccererer");
}
};
myInterface.test();
myInterface.aa();
}
}
interface MyInterface {
void test();
void aa();
}
/*
class CC implements MyInterface{
@Override
public void test() {
System.out.println("abc");
}
}*/
想要一个正常类得子类对象:
public class MyTest3 {
public static void main(String[] args) {
//Son son = new Son();
Father f= new Father(){
@Override
public void hehe() {
super.hehe();
}
};
}
}
class Father{
public void hehe(){
}
}
/*
class Son extends Father{
}
*/
20.匿名内部类的方法调用
匿名内部类作为参数传递:
public class MyTest {
public static void main(String[] args) {
//匿名内部类,经常作为参数或返回值比较方便
//如果你以后看到一个方法的形参要一个抽象类 类型,你就传递一个该抽象类的子类对象。
// CC cc = new CC();
// set(cc);
BB bb = new BB() {
@Override
public void hehe() {
System.out.println("ccccccccccccccccccccccc");
}
};
set(bb);
set(new BB() {
@Override
public void hehe() {
System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaa");
}
});
set(new MyInterface() {
@Override
public void show() {
System.out.println("cccccccccccccccccccc");
}
});
MyInterface my= new MyInterface() {
@Override
public void show() {
System.out.println("dddddddddddddddddddddddddd");
}
};
set(my);
}
public static void set(BB bb) {
bb.hehe();
}
public static void set(MyInterface myInterface) {
myInterface.show();
}
}
abstract class BB {
public abstract void hehe();
}
interface MyInterface{
void show();
}
/*
class CC extends BB{
@Override
public void hehe() {
System.out.println("aaaaaaaaaaaaaaaaaaa");
}
}
*/
匿名内部类作为返回值:
public class MyTest2 {
public static void main(String[] args) {
EE ee = getEE();
ee.hehe();
EE ee1 = getEE();
ee1.hehe();
}
//当你以后看到一个方法的返回值类型要一个抽象类类型,你就返回该抽象类的子类对象
public static EE getEE(){
// TT tt = new TT();
EE ee = new EE() {
@Override
public void hehe() {
System.out.println("rrrrrrrrrrrrrrrrrrrrrrr");
}
};
return ee;
}
}
21.匿名内部类在开发中的应用
1.问题引出
首先回顾我们曾经讲过的方法的形式参数是引用类型的情况,
我们知道这里需要一个子类对象。而匿名内部类就是一个子类匿名对象,
所以,可以使用匿名内部类改进以前的做法。
2.代码如下
//这里写抽象类,接口都行
abstract class Person {
public abstract void show();
}
class PersonDemo {
public void method(Person p) {
p.show();
}
}
class PersonTest {
public static void main(String[] args) {
//如何调用PersonDemo中的method方法呢?
new PersonDemo().method(new Person() {
@Override
public void show() {
System.out.println("abc");
}
});
}
}
22.匿名内部类中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);//23
System.out.println(Inter.a);//23 变量a是公共得静态常量
}
}.show();
}
}
23.匿名内部类的面试题
面试题
按照要求,补齐代码
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();
}
}
要求在控制台输出”HelloWorld"method()方法直接用类名Outer打点掉用,所以肯定是静态方法;
调用完method方法之后紧接着就打点调用了Inter中得show方法,用了链式编程写法,所以肯定有一个返回值,返回值类型就是Inter类型,然后就用匿名内部类作为返回值,并重写show方法;
24.类中定义接口(内部接口)
public class MyTest {
public static void main(String[] args) {
/*
Wai.MyInterface myInterface = new Wai.MyInterface() {
@Override
public void show() {
System.out.println("重写了接口的方法");
}
};
myInterface.show();
*/
Wai wai = new Wai();
wai.hehe();
}
}
class Wai {
//内部接口
private interface MyInterface {
void show();
}
public void hehe() {
MyInterface myInterface = new MyInterface() {
@Override
public void show() {
System.out.println("abc");
}
};
myInterface.show();
}
}