1 类名作为形参和返回值
方法的形参是类名,需要的是该类的对象
当你调用该方法的时候其实需要传递的实参是该类的实例对象
方法的返回值是类名,其实返回的是该类的对象
当你调用该方法的时候能获得该类的实例对象
===================================================================================
2 抽象类名作为形参和返回值
方法的参数是抽象类,在调用的时候需要传递该抽象类的子类对象
方法的返回值是抽象类,在调用该方法的时候返回的是该抽象类的子类对象
===================================================================================
3 接口名作为形参和返回值
方法的参数是接口的时候,调用该方法传递的实参是该接口的实现类
方法的返回值是接口的时候,调用该方法的时候返回的是该接口的实现类
===================================================================================
4 内部类:
内部类:其实并不是什么地方都能用上
内部类分类: 成员内部类,静态内部类,局部内部类,匿名内部类
语法:类中定义类
class A{
class B{ /*
可能在刚开始学习类的时候也这样写过,当时可能是没有注意缩进格式
B就是A的内部类 编译之后会生成两个class文件 A.class A$B.class 说明内部类只是在编译期有效
到运行期 A和B是没有包含关系 是两个相互独立的类 所以内部类仅仅是一个编译期的语法
外部类名称$内部类名称.class
*/
}
}
作用: 1 防止类名冲突 同一个包内定义两个同名的类是不允许的 但是可以创建同名的内部内
com.itheima.classA
com.itheima.Fu.classA
2 实现多继承
class A extends 类名{
class B extends 类名{//还是单继承 但是内部内部可以访问外部类的所有属性和方法 包括私有
}
}
3 内部类可以很好的实现隐藏:一般的非内部类,是不允许有 private 与protected权限的,但内部类可以
所以内部类往往都定义了企业最核心的逻辑代码
缺点:使程序结构不清晰。
===================================================================================
5 成员内部类:
1成员内部类
class Outer{
//外部类私有属性
private int a=100;
//构造方法
public Outer(int a){
this.a=a;
}
public void method(){
Inner in=new Inner();
in.print();
}
class Inner{//这个inner就是outer类的成员内部类 它的定义位置是Outer类的成员位置上 可以用private public修饰
//里边和正常定义类一样
int a=20;
public void print(){
//那能不能打印a a的作用范围是整个Outer类 所以是可以打印的 inner在Outer类的封装范围内
System.out.println(a);
System.out.println(Outer.this.a);
}
//static int b=10; //内部类不能有静态成员
static final int b=10;//可以有常量
}
}
public class 内部类 {
public static void main(String[] args) {
//我想在主方法中创建一个inner对象调用打印方法
// Outer.Inner in=new Outer.Inner();
// in.print();
/*
a是outer里边的私有属性整个属性是什么时候创建的 ?-->是在Outer创建对象的时候才有的 你现在没有创建对象呢
a是不存在的能进行打印吗,
由于成员内部类能访问外部类的私有属性,这句话潜意识的就是在说 你的先创建一个外部类对象 然后通过外部类对象
创建内部类对象
*/
Outer o1=new Outer(100);
Outer o2=new Outer(200);
Outer.Inner in = o2.new Inner(); //语法有点奇怪
//Outer.Inner in=new Outer().new Inner();
in.print();
//如果我给内部定义静态属性
// 在内部类定义和外部类同名属性
//调用 System.out.println(Outer.this.a);
}
}
使用格式: 外部类对象.内部类对象 对象名 = new 外部类对象().new 内部类对象();
注意点: 1成员内部类和成员属性定义位置一样
2成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员),
3创建成员内部类必须先创建外部类对象,通过外部类对象.new 构造内部类对象
4成员内部类中不能有静态成员
5当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,
即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类. this .成员变量
外部类. this .成员方法
6成员内部类可以有常量
问题思考:为什么成员内部类不能有静态成员?
JVM的类加载规则 :
1. static类型的属性和方法,在类加载的时候就会存在于内存中。
2. 要想使用某个类的static属性和方法,那么这个类必须要加载到JAVA虚拟机中。
3. 非静态内部类并不随外部类一起加载,只有在实例化外部类之后才会加载。
内部类是外部类的成员,成员在外部类创建对象后才会初始化,但是静态属性要求在创建对象之前完成,这样就产生了矛盾
public class Outer{
int x;
class Inner{
static int a = 0;//这样写是不合法的.
static final int b=0;//这样写是合法的
}
}
java类加载顺序,首先加载类,执行static变量初始化,接下来执行对象的创建,
如果我们要执行代码中的变量int a 初始化,那么必须先执行加载外部类,再加载内部类,
最后初始化静态变量 a ,问题就出在加载内部类上面,我们可以把内部类看成外部类的非静态成员,
它的初始化必须在外部类对象创建后以后进行,要加载内部类必须在实例化外部类之后完成 ,
java虚拟机要求所有的静态变量必须在对象创建之前完成,这样便产生了矛盾。
将class Inner看作外部类的非静态成员,它属于对象Outer(即new 出来的Outer()),
static int a 属于类Inner 所以先于对象Inner Outer创建出来,矛盾
而java常量放在内存中常量池,它的机制与变量是不同的,编译时,加载常量是不需要加载类的,所以就没有上面那种矛盾。
静态的东西需要在编译时分配内存,而非静态内部类是在实例化的时候才分配内存。
所以现在的情况就是有了东西没地方放 static int a 没地方放,因为class Inner还没有实例化
问题思考: 为什么内部类能访问外部类的成员
因为内部类持有外部类的引用
class Outer{
private int a=100;
class Inner{
int b=20;
public void print(){
System.out.println(b);//this.b
System.out.println(a);//Outer.this.a
}
}
}
成员内部类的特征:
1 名义上内部类 实际上是外部类,每个内部类都有自己独立的.class文件 命名 外部类$内部类.class
2 封装性更高 可以作成私有 内部类往往都定义了企业最核心的内容
3 大多数情况下 内部类的对象都是由外部类去创建的(也就是说在外部类中new 内部类对象)
4 成员内部类能够持有外部类的this
内部类不会在外部类初始化的时候被初始化,
===================================================================================
6 局部内部类:
public class 内部类 {
public static void main(String[] args) {
Outer out=new Outer();
out.method(10);
}
}
class Outer{
private int a=10;
public void method(int b){
int c=20;
class Inner{//作用范围就是method方法内部
public void print(){//我想调用这个方法怎么弄 只能抓紧在method方法内部做 出了这个方法就不能用了
System.out.println("hehe");
System.out.println(a);
System.out.println(b);
System.out.println(c);
//b=20; //若局部变量不是final的,其取值就可以被修改
}
}
Inner in=new Inner();
in.print();
}
}
总结: 1 定义在方法中的内部类使用范围等同于局部变量 局部内部类不仅可以访问外部类的私有成员
还可以访问所在外部类中方法的局部变量 也就是说局部内部类持有外部类的 this
2 被内部类访问的局部变量会被拷贝一份到内部类中,即Inner中存在一个成员变量,用于记录局部变量a的值。
若局部变量不是final的,其取值就可以被修改,而Inner对象中保存的是其原来的值,这就会出现数据不同步的问题。
Java为了避免数据不同步的问题,做出了内部类只可以访问final的局部变量的限制。
在java8中,可以不使用final,如果局部变量被内部类访问,那么该局部变量相当于自动使用了final修饰。
3 封装性比成员内部类还要高,只能在外部类的某个方法中去定义使用
4 由于和局部变量平级 所以不能够使用 public protected private 修饰局部内部类 final 是可以修饰的不能被继承
===================================================================================
7 匿名内部类
4匿名内部类
概念: 顾名思义是一个没有名字的内部类
特点:1)特殊的局部内部类
2)继承一个类或者是实现一个接口
3)只会创建该类的一个对象
4)只能用默认的构造方法
格式: new 接口/类(){
};
理解: 将(继承/实现)(方法重写)(对象创建) 三个步骤合为一个步骤
public class demo1 {
public static void main(String[] args) {
Teacher teacher = School.getTeacher(2);
teacher.Teach();
Teacher teacher1 = School2.getTeacher(1); //接口引用指向子类对象
teacher1.Teach();
}
}
//创建一个接口
interface Teacher {
public void Teach();
}
class School {
//一个静态方法 获取一个老师对象
public static Teacher getTeacher(int i) {
//创建局部内部类分别由两个老师实现Teacher 并重写Teach方法
class CangTeacher implements Teacher {
public void Teach() {
System.out.println("Cang teachers");
}
}
class ChengTeacher implements Teacher {
public void Teach() {
System.out.println("Chen teachers");
}
}
//当外部调用getTeacher方法传入参数由i接受 并判断返回哪个老师
if (i % 2 == 0) return new CangTeacher();
else return new ChengTeacher();
/*
无论是苍老师 还是陈老师 我都只创建了一次 所以当三个条件满足之后 我就能把这个局部内部类改造成为匿名内部类
改造方式
new 接口(){
实现这个接口中的方法
}
其实我要new的不是接口 我需要的是一个类把接口实现了 {} 这就是一个类的隐含的实现接口, 这个类叫什么不知道
匿名内部类是把 定义类,实现接口 new对象和在一起了
其实匿名内部了类的语法完全可以用局部内部类代替 匿名代码少写一行 丢掉的是程序的可读性
它的应用很广泛 很多程序员都在使用,可以让人在编程的时候思路不断
匿名内部类能定义构造方法吗?
匿名内部类没名字不能定义构造方法只能使用默认的构造方法
*/
}
}
//改造
class School2 {
//一个静态方法 获取一个老师对象
public static Teacher getTeacher(int i) {
if(i%2==0) return new Teacher() {
@Override
public void Teach() {
System.out.println("苍老师教你生理卫生");
}
};
else return new Teacher() {
@Override
public void Teach() {
System.out.println("陈老师教你摄影技术");
}
};
}
}
内部类是一个编译期的语法 在运行的时候是两个独立的类 那为什么还要让一个类成为另一个类的内部类?
1 内部类可以访问外部类的私有成员而不破坏封装
2 接口公开 接口的实现类作为内部类隐藏起来 强制弱耦合
//定义一个老师接口有一个教的方法
interface Teacher2{
public void Teach();
}
//苍老师实现该接口
class CangTeacher implements Teacher{
public void Teach(){
System.out.println("Cang teachers");
}
}
//陈老师实现该接口
class ChenTeacher implements Teacher{
public void Teach(){
System.out.println("Da teachers");
}
}
//改造成匿名内部类
class School3{ //
public static Teacher getTeacher(int i){
if(i%2==0)return new Teacher2() {
@Override
public void Teach() {
System.out.println("苍老师teacher");
}
} ;
else return new Teacher2() {
@Override
public void Teach() {
System.out.println("大老师讲课");
}
};
}
}
public class demo2 {
public static void main(String[] args) {
//我们这样设计希望 学生和老师之间是弱耦合的
// 如果换个老师是对学生之间是没有影响的
//只能学校去改动getTeacher()代码
Teacher t = School3.getTeacher(0);
t.Teach();
//但是学生还可以这样写
CangTeacher c=new CangTeacher();
c.Teach();
/*
上边也是调用苍老师的方法 下边也是调用苍老师的方法 但是如果把代码写成下面的样子我们的一番苦心就白费了
上来绕开接口和学校,直接找了苍老师 ---->这是可以的,但是我们利用接口实现弱耦合办不到了,
这事情如果是学生们都要求苍老师讲课程,学校就应该着急了,
所以为了杜绝学生这样写代码
需要从新改造
把两个老师 只能在学校的getTeacher()中使用, 所以把这两个做成局部内部类 只能学校使用,
站在学生角度只能看到 老师接口 还有学校
*/
}
}
//解析组成部分
整体会隐式的创建了匿名内部类的对象
new Teacher2() {
@Override
public void Teach() {
System.out.println("苍老师teacher");
}
} ;
匿名内部类指的是
//继承/实现
{
@Override
public void Teach() {
System.out.println("苍老师teacher");
}
} ; //有类的结构但是没有类名
//方法重写
@Override
public void Teach() {
System.out.println("苍老师teacher");
}
//对象创建
new Teacher2()
===================================================================================
8 匿名内部类在开发中的使用
当其他方法的参数是一个接口的时候就可以直接使用匿名内部类创建对象当实际参数传递
内部类是一个编译期的语法 在运行的时候是两个独立的类 那为什么还要让一个类成为另一个类的内部类?
1 内部类可以访问外部类的私有成员而不破坏封装
2 接口公开 接口的实现类作为内部类隐藏起来 强制弱耦合
//定义一个老师接口有一个教的方法
interface Teacher2{
public void Teach();
}
//苍老师实现该接口
class CangTeacher implements Teacher{
public void Teach(){
System.out.println("Cang teachers");
}
}
//陈老师实现该接口
class ChenTeacher implements Teacher{
public void Teach(){
System.out.println("Da teachers");
}
}
//改造成匿名内部类
class School3{ //
public static Teacher getTeacher(int i){
class CangTeacher implements Teacher{
public void Teach(){
System.out.println("Cang teachers");
}
}
class DaTeacher implements Teacher{
public void Teach(){
System.out.println("Da teachers");
}
}
if(i%2==0)return new CangTeacher();
else return new DaTeacher();
}
//该方法的参数是一个接口引用
public static void method(Teacher2 t){}
}
public class demo2 {
public static void main(String[] args) {
//我们这样设计希望 学生和老师之间是弱耦合的
// 如果换个老师是对学生之间是没有影响的
//只能学校去改动getTeacher()代码
Teacher t = School3.getTeacher(0);
t.Teach();
//但是学生还可以这样写
CangTeacher c=new CangTeacher();
c.Teach();
/*
上边也是调用苍老师的方法 下边也是调用苍老师的方法 但是如果把代码写成下面的样子我们的一番苦心就白费了
上来绕开接口和学校,直接找了苍老师 ---->这是可以的,但是我们利用接口实现弱耦合办不到了,
这事情如果是学生们都要求苍老师讲课程,学校就应该着急了,
所以为了杜绝学生这样写代码
需要从新改造
把两个老师 只能在学校的getTeacher()中使用, 所以把这两个做成局部内部类 只能学校使用,
站在学生角度只能看到 老师接口 还有学校
*/
//当调同这个方法的时候需要一个Teacher2类型的对象 但是Teacher2是接口 所以要给一个实现类
//直接用匿名内部类去做
School3.method(new Teacher2() {
@Override
public void Teach() {
System.out.println("Cang teachers");
}
});
}
}
===================================================================================
9 Math
Math 数学类
包含基本数学运算的类
public final class Math 是一个被final修饰的类 是一个最终类
类中所有的方法都是静态方法 被static修饰 可以用类名直接调用
常用方法:
1 public static int abs(int a) //返回参数的绝对值 正数的绝对值是它本身 负数的绝对值是它的相反数
2 public static double ceil(double a) //向上取整 舍去小数 保留整数部分然后+1
3 public static double floor(double a)//向下取整 直接舍去小数部分 保留整数部分
4 public static int round(float a) //四舍五入
5 public static int max(int a,int b) //返回两个参数中较大的数据
6 public static int min(int a,int b) //返回两个参数中较小的数据
7 public static double pow(double a,double b) // 返回a的b次幂(方)的值
8 public static double random() // 返回double的正值 [0.0,1.0)
思考 //生成1-10之间的随机数 int num = (int)Math.floor(Math.random() * 10 + 1);
===================================================================================
10 system
===================================================================================
11 Object的toString()
===================================================================================
12 Object中的equals()
===================================================================================
13 冒泡排序原理
===================================================================================
14 冒泡排序实现代码
===================================================================================
15 Arrays