目录
接口 interface
接口只能定义常量与抽象方法
接口是特殊的抽象类
接口的方法,默认公开抽象[public abstract] 可省略
接口 可以继承[extends]多个接口
“实现”接口 [实现类] implements 实现接口重写抽象方法与继续抽象类
一个子类可实现多个接口 多实现
抽象类与接口区别
抽象类是类class;
具有构造函数,定义常量、成员变量、成员方法即已实现的成员方法与未实现的成员方法[抽象方法];
子类继承抽象类采用关键字extends,一个类只允许继承一个父类;
接口是interface接口;
只有定义常量与抽象方法[即未实现的方法体];
子类实现接口采用implements,一个类允许实现多个接口;
且接口可以使用extends继承多个接口;
接口的简单使用
接口 interface代码
public interface Demo1Fly {//飞
//int b;接口无成员变量
//抽象的常量
public static final int LIFE=100;
//接口的方法 默认公开抽象
//可省略public abstract
public abstract void fly();
//可重载
void fly(String good);//借助于什么力量飞行
}
interface Run{ //跑
public static final int LIFE=100;
//接口方法 省略public abstract
void run();//接口的方法 默认public abstract
}
"实现"接口 implements
继续抽象类 与 实现接口重写抽象方法
//继续抽象
abstract class Person implements Run{
}
//继承
class doctor extends Person{
@Override
public void run() {
System.out.println("医生在跑...");
}
}
//实现类
class Brid implements Demo1Fly,Run{
@Override
public void fly() {
System.out.println("鸟在天上飞...");
}
@Override
public void fly(String good) {
System.out.println("鸟在飞借助与"+good);
}
@Override
public void run() {
System.out.println("鸟有时走路....");
}
}
调用实现类 main
向上造型
class TestBird{
public static void main(String[] args) {
//创建鸟,赋值给鸟类型 调用所有方法
Brid b1=new Brid();
b1.fly();
b1.fly("翅膀");
b1.run();
//创建鸟,赋值给Demo1Fly类型 调用所有方法
Demo1Fly f1=new Brid();
f1.fly();
f1.fly("翅膀2");
//Demo1Fly类型中 没有Run类型的run()方法
//f1.run();
//创建鸟,赋值给Run类型 调用所有方法
Run r1=new Brid();
//Run类型中 没有Demo1Fly类型的fly()方法
//r1.fly();
//r1.fly("翅膀3");
r1.run();
}
}
接口继承[extends]多个接口
接口的多继承
//接口,通过extends 实现继承多个接口
interface YunDonYuan extends Run,Demo1Fly{ //运动员
//继承Run,Demo1Fly接口之后,有三个方法
void excise();//练习
void test();//考试
}
实现接口 implements 同时继承extends 类
定义游泳运动员 队员编号 身高 体重 继续People
实现YUNDonYuan接口
创建游泳运动员对象 分别赋值给自己和父类的引用
class People{ //人
String name;//名字
char sex;//性别
String sfZheng;//身份证
}
class PingPangPeople extends People implements YunDonYuan{ //乒乓球运动员
String id; //队员编号
double height;//身高
double weight;//体重
public void game(){ //比赛
System.out.println("乒乓运动员比赛....");
}
@Override
public void fly() {
//空实现
}
@Override
public void fly(String good) {
}
@Override
public void run() {
}
@Override
public void excise() {
}
@Override
public void test() {
}
}
调用实现类 main
class TestYouYong{
public static void main(String[] args) {
YouYongPeople y1=new YouYongPeople();
//向上造型
People y2=new YouYongPeople();
YunDonYuan y3=new YouYongPeople();
Demo1Fly y4=new YouYongPeople();
Run y5=new YouYongPeople();
}
}
@FunctionalInterface 函数式接口
注解:放在方法前 类前面 变量前面 有特殊功能 对类、方法、变量进行一些作用
@FunctionalInterface 函数式接口,只能放在接口前面,且接口内部只能有一个抽象方法
//@FunctionalInterface 函数式接口 只能放在接口前面 接口内部只能有一个抽象方法
@FunctionalInterface
public interface Demo2Eat {
void eat();//抽象方法 省略了public abstract
// void eat1();//编译错误
//接口头上有@FunctionalInterface ,接口内部只能有一个抽象方法
}
内部类
一个类定义在另外一个类的内部,在内部的类称内部类,外部的类称外部类
内部类 一般private 直接使用外部类的成员方法
内部类 直接使用外部类的成员变量[无关访问权限]
外部类无法调用内部方法与成员变量
内部类不能独立与外部类存在,需先创建外部类再创建内部类
内部类未被创建,则无法调用用其内部类中的方法与属性
功能:类存在的价值仅仅只为某个类服务
public class Demo3Outer {//外部类
private int x;
private int y;
public Demo3Outer(int x,int y){
this.x=x;
this.y=y;
}
public void print(){
System.out.println("["+x+","+y+"]");
}
class Inner{ //内部类
public int sum(){
print(); //内部类 直接使用外部类的成员方法
return x+y;
//内部类 直接使用外部类的成员变量[无关访问权限]
}
}
}
class TestInner{
public static void main(String[] args) {
// Inner i=new Inner();//内部类不能独立与外部类存在
Demo3Outer outer=new Demo3Outer(3,6);
Demo3Outer.Inner inner=outer.new Inner();
System.out.println(inner.sum());
//内部类未别创建,则无法使用其内部类中的方法与属性
}
}
局部内部类
定义在方法中的类,称为局部内部类;局部内部类只能在所在的成员方法中使用
局部内部类,与类一致,可有成员变量与成员方法;
只能在所在的成员方法中被创建,被调用成员方法与成员变量
public class Demo5 {
public void fun(){
//局部内部类
class Inner2{
int x;
//局部内部类的方法名可自定义
public void show(){
System.out.println("这是局部内部类"+x);
}
}
Inner2 inner2=new Inner2();
inner2.x=5;
inner2.show();
}
public void show(){
//Inner2 inner2=new Inner2();
//编译错误 局部内部类只能用在所在的成员方法中
//即只能在fun()方法定义的只能在fun()中创建与调用
System.out.println("这是Demo5的一个成员方法");
}
public static void main(String[] args) {
Demo5 d5=new Demo5();
d5.fun();
d5.show();
}
}
匿名内部类
匿名内部类,在一段程序中需要创建一个类的对象(这个类型需实现某个接口或继承某个抽象类),在对象创建后,这个价值就不存在了,这个类不必命名
匿名内部类[针对于抽象类与接口]
new 类/接口{重写抽象方法}
继承类[包括抽象类] 用 extends
实现接口 用 implements
public class Demo4Timer1 {
public static void main(String[] args) {
Timer t=new Timer();
t.schedule(new TimerTask() {
//TimerTask是一个抽象类
//这里使用了匿名内部类
//重写抽象方法
@Override
public void run() {
System.out.println("该起床了....");
}
},1000,5000);
}
}
利用接口/抽象类创建对象 编译错误
Fly2是接口
Fly2 fly2=new Fly2()
编译错误 接口/抽象类无法创建对象
解决方式
向上造型
[写一个类继承接口/抽象类并重写抽象方法 ]
多次使用
匿名内部类[便于只使用一次]
new 类/接口{重写抽象方法}
interface Fly2{
void fly();
}
class TestFly2{
public static void main(String[] args) {
//Fly2 fly2=new Fly2() //编译错误 接口/抽象类无法创建对象
//解决方式 向上造型[写一个类继承接口/抽象类并重写抽象方法 多次使用] 匿名内部类[便于只使用一次]
//匿名内部类
Fly2 fly1=new Fly2() { //创建一个对象重写抽象方法 匿名的
@Override
public void fly() {
System.out.println("匿名内部类重写,便于只一次创建对象");
}
};
Fly2 fly3=new A();
}
}
class A implements Fly2{
@Override
public void fly() {
System.out.println("继承继承接口/抽象类并重写抽象方法,多次调用创建对象");
}
}
静态内部类 static
static修饰的成员内部类称静态内部类,在外部加载时存在
静态内部类随着外部类加载而存在 或 直接new创建对象
静态内类独自有一份存起来 可以通过类名调用静态
静态内部类中 也可以有 非静态方法与非静态成员变量,这部分需要先创建对象才能调用
例如: Demo6.Inner
public class Demo6 {
int x;
int y;
static int m;
static int n;
//静态类
static class Inner{
//静态内类独自有一份存起来 可以通过类名调用静态
static int sum=0;
public void fun(){
// int sum=x+y; 静态无法用非静态的x,y
int sum=m+n;
//静态的可在静态类中的非静态方法中使用
System.out.println("这是雇一个静态内部类,非静态方法");
}
public static void print(){
int sum=m+n;
//静态的可在静态类中的静态方法中使用
System.out.println("这是雇一个静态内部类,静态方法");
}
}
public void show(){
Inner.sum++;
Inner.print();
//外部可以使用静态内部类的静态方法与静态变量
System.out.println("这是一个外部的非静态....");
}
public static void main(String[] args) {
//完整写法 静态内部类随着外部类加载而存在
静态内部类中的非静态方法,需要先创建类再调用
Inner inner=new Demo6.Inner();
inner.fun();
//静态内部类中的静态方法 直接访问
Demo6.Inner.print();
//Demo6.Inner.fun();
// 编译错误
//fun()是静态内部类的非静态方法 无法直接访问
//直接new创建对象
new Inner().fun();
}
}
静态的可以被静态或者非静态的直接使用或调用
但静态的,不能直接调用非静态的,只有先创建对象才能调用非静态的
字符串的常量池与创建对象
new String(); 是创建一个引用对象
直接字符串 是常量池 String str = “a”;
若赋值为常量值
首先到常量池,找是否有该对象 ,找到了就把引用该地址赋值给变量;
找不到此对象,就该常量池创建这个对象,然后把地址赋值为变量
字符串的常量池与创建对象对比
//new String(); 是创建一个引用对象
//直接字符串 是常量池String str = "a";
public class Demo8 {
public static void main(String[] args) {
// 字符串对象
String str = "a";
// str是一个引用你该地址, 指向对象
String str1 = new String("a");
// str1是一个引用你该地址, 指向对象。
String str2 = "a" ;
// 到常量池,找是否有对象”a“ ;
//找到了,就把引用该地址赋值给str2
//找不到,就再常量池创建这个对象
//最后然后把地址赋值为str2.
String str3 = new String("a");
// new , 就创建对象
// 等号就是再比较对象的引用地址是否相同。
System.out.println(str == str1); // false
System.out.println(str == str2); // true
System.out.println(str == str3); // false
System.out.println(str1 == str3); // false
}
}
传值和传引用
一个方法参数是8大基本数据类型
该方法不会对实际参数造成影响
一个方法的参数为引用类型
直接修改该参数会对其造成影响
若方法中又创建了新对象,则不会对实际参数有影响
一个方法参数为字符串[引用类型]
该方法赋值一个新字符串,不会对实际参数造成影响
方法参数为8大基本数据类型
public static void main(String[] args) {
Demo7 d=new Demo7();
//一个方法参数是8大基本数据类型,该方法不会对实际参数造成影响
int x=8;
int y=9;
d.p(x,y);
System.out.println(x+"==="+y);
//8===9 未改变值
}
public void p(int x,int y){
x=5;
y=2;
System.out.println(x+"==="+y);//5===2
}
方法参数为引用类型
public static void main(String[] args) {
Demo7 d=new Demo7();
//一个方法的参数为引用类型 直接修改该参数会对其造成影响
Piont p=new Piont();
p.x=7;
p.y=2;
d.p(p);
System.out.println(p.x+"==="+ p.y);
//2===8 值改变
//方法的参数为引用类型 若方法中又创建了新对象 则不会对实际参数有影响
p.x=3;
p.y=5;
d.p2(p);
System.out.println(p.x+"==="+ p.y);
//3===5 值未变
}
public void p(Piont p){
p.x=2; //未有新对象产生 变量指向最初对象
p.y=8;
System.out.println(p.x+"==="+p.y);//2===8
}
public void p2(Piont p){
p=new Piont();
//产生了新对象 变量指向新对象
System.out.println(p.x+"==="+p.y);//0===0
}
class Piont{
int x;
int y;
}
方法参数为字符串[引用类型]
public static void main(String[] args) {
Demo7 d=new Demo7();
//一个方法参数为字符串[引用类型] 该方法赋值一个新字符串 不会对实际参数造成影响
String strHello = new String("hello");
d.p(strHello);
// 引用传递: fun3函数内部,修改的是局部变量str的引用地址
System.out.println("strHello:" + strHello);
//strHello:hello
}
public void p(String s){
s= "abcd";
// 字符串常量池,把常量池中的"abcd"的引用赋值给str 相当于new了一个对象
System.out.println("str:" + s);
//str:abcd
}