接口
我们通过interface关键字来定义接口
接口不能创建普通方法,只可以定义抽象方法
接口中没有构造方法,接口不可以实例化
接口中的是静态常量,没有成员变量,默认写法是:int age=20;实际上的写法是public static final int age=20
接口中抽象方法可以简写成void say(),接口会自动给方法拼接public abstrac
如果一个类没有明确指定他的父类,那么他默认继承顶级父类Object
接口可以继承接口,而且还可以多继承,也就是一个子接口继承多个父接口,多个接口之间使用逗号分隔
实现类与接口是实现的关系,并且实现类可以实现多个接口,接口之间用逗号隔开
对于Java中的类而言:遵循单继承,多实现的规则
对于Java中的接口而言,遵循:既可以单继承又可以多继承的规则
实现类如果想要实现接口定义的功能,需要与接口建立实现关系。通过关键字implements来建立实现类 实现 接口的关系
方案一:如果实现类与接口实现关系以后,可以选择不实现接口中的抽象方法,把自己变成一个抽象类*/
方案二:如果实现了与接口建立实现关系以后,还可以选择实现接口中所有的抽象方法,把自己变成一个普通子类
案例
/*本类用于面向接口编程*/
public class TestTeacherInter {
public static void main(String[] args) {
CBGTeacher c=new CBGTeacher();
c.ready();
c.teach();
}
}
//1.定义老师接口--接口是先天设计的结果,最先设计的就是接口,要制定规则
interface Teacher{
//2.定义接口里的方法
void ready();
void teach();
}
class CBGTeacher implements Teacher{
@Override
public void ready() {
System.out.println("正在备课。。。");
}
@Override
public void teach() {
System.out.println("授课电商项目");
}
}
class ACTTeacher implements Teacher{
@Override
public void ready() {
System.out.println("正在备课中2.。");
}
@Override
public void teach() {
System.out.println("正在基础加强");
}
}
abstract class SCDTeacher implements Teacher{
@Override
public void teach() {
System.out.println("正在研发新课程。。。");
}
}
内部类
格式:外部类名.内部类名 对象名=new 外部类对象.内部类对象
外部类如果想要使用内部类的资源,就必须先创建内部类对象,然后通过内部类对象来调用内部类的资源
根据内部类所在位置的不同,分为:成员内部类(类里方法外)与局部内部类(方法里)
内部类可以直接使用外部类的资源,包括私有资源
案例
/*本类用于内部类的入门案例*/
public class TestInner1 {
public static void main(String[] args) {
//3.创建内部类对象,使用内部类资源
/*格式:外部类名.内部类名 对象名=new 外部类对象.内部类对象*/
Outer.Inner oi=new Outer().new Inner();
oi.delete();
System.out.println(oi.sum);
//4.创建外部类的匿名对象
new Outer().find();
}
}
//1.创建外部类
class Outer{
//1.1创建外部类的成员变量
String name;
private int age;
//1.2创建外部类的成员方法
public void find(){
System.out.println("Outer...find()");
// System.out.println(sum);
// delete();//
/*外部类如果想要使用内部类的资源,就必须先创建内部类对象
* 然后通过内部类对象来调用内部类的资源*/
Inner in=new Inner();
System.out.println(in.sum);
in.delete();
}
//2.创建内部类
/*根据内部类所在位置的不同,分为:成员内部类(类里方法外)与局部内部类(方法里)*/
class Inner{
//2.1定义内部类的成员变量
int sum=10;
//2.2定义内部类的成员方法
public void delete(){
System.out.println("Inner...delete()");
//5.内部类可以使用外部类的资源
/*内部类可以直接使用外部类的资源,包括私有资源*/
System.out.println(name);
System.out.println(age);
find();
}
}
}
当内部类被private修饰
/*本类用于测试成员内部类被private修饰*/
public class TestInner2 {
public static void main(String[] args) {
// Outer2.Inner2 oi = new Outer2().new Inner2();
// oi.eat();
/*如果Inner2被private修饰,无法直接创建对象*/
Outer2 o=new Outer2();
o.getInner2Eat();
}
}
//1.创建外部类
class Outer2{
//6.提供本类的公共方法,在本方法创建内部类的对象,使用内部类功能
public void getInner2Eat(){
Inner2 i=new Inner2();
i.eat();
}
//2.创建成员内部类
//5.使用private修饰成员内部类
private class Inner2{
//3.创建成员内部类的普通方法
public void eat(){
System.out.println("Inner2的eat()");
}
}
}
成员内部类被static修饰
/*本类用于测试成员内部类被static修饰*/
public class TestInner3 {
public static void main(String[] args) {
//4.1创建普通内部类对象并调用内部类的功能
// Outer3.Inner3 oi = new Outer3().new Inner3();
// oi.show();
//4.2创建匿名内部类对象并调用内部类的功能
// new Outer3().new Inner3().show();
/*现象:当成员内部类被static修饰以后,new Outer3()外部类会报错
* 结论:创建静态成员内部类对象时,不需要先创建外部类对象,直接通过类名调用*/
Outer3.Inner3 oi3 = new Outer3.Inner3();
oi3.show();
new Outer3.Inner3().show();//创建静态内部类的匿名对象
//8.访问静态内部类的静态资源--链式加载
Outer3.Inner3.show2();//没有创建任何对象,都是通过类名调用的
}
}
//1.创建外部类
class Outer3{
//2.创建成员内部类
//5.测试成员内部类被static修饰--很少用!!!浪费内存!!!
static class Inner3{
//3.创建成员内部类的方法
public void show(){
System.out.println("Inner3的show()");
}
//7.创建成员内部类的静态方法
static public void show2(){
System.out.println("Inner3的show2()");
}
}
}
局部内部类
/*本类用来测试局部内部类*/
public class TestInner4 {
public static void main(String[] args) {
/*如何使用局部内部类的资源?
* 注意:直接调用外部类的show()是无法触发局部内部类的功能的
* 要执行局部内部类的功能,必须先创建局部内部类的对象并调用对应的功能*/
//7.测试第二次:当我们在show()里
new Outer4().show();
}
}
//1.创建外部类
class Outer4{
//2.创建外部类的成员方法
public void show(){
System.out.println("Outer4的show()");
//3.创建局部内部类--不太常用
/*局部内部类的位置:方法里*/
class Inner4{
//4.创建局部内部类自己的资源
String name;
int age;
public void eat(){
System.out.println("Inner4的eat()");
}
}
/*6.创建局部内部类对象并调用局部内部类的功能*/
Inner4 inner4=new Inner4();
System.out.println(inner4.age);
inner4.eat();
}
}
匿名内部类
1.匿名内部类没有名字,通常与匿名对象结合在一起使用
2.匿名对象只能使用一次,一次只能调用一个功能
3.匿名内部类充当了实现类的角色,去实现接口/抽象类中的抽象方法,只是没有名字而已
public class TestInner5 {
public static void main(String[] args) {
//传统方式:创建接口+创建接口实现类+实现类实现接口中的所有抽象方法
//创建接口实现类的对象+通过对象调用实现了的功能
//3.创建接口对应的匿名对象与匿名内部类,并调用实现后的save()
new Inner5(){
@Override
public void save(){
System.out.println("保存");
}
@Override
public void get(){
System.out.println("得到");
}
}.save();
//5.创建抽象类的匿名对象和匿名内部类
new Inner6(){
@Override
public void play(){
System.out.println("玩代码");
}
}.play();
//7.创建普通类的匿名对象并调用方法
new Inner7().study();
new Inner7().powerUp();
}
}
//1.创建接口
interface Inner5{
//2.定义接口中的抽象方法
void save();
void get();
}
//4.创建抽象类
abstract class Inner6{
public void say(){//普通方法
System.out.println("在说话");
}
public abstract void play();//抽象方法
}
//6.创建普通类
class Inner7{
public void study(){
System.out.println("再冷的天我也要学习");
}
public void powerUp(){
System.out.println("我们会越来越强");
}
}
String类的使用
创建String对象的方式一:字符串类型底层维护的是char[],存在堆内存中
char[] values={'a','b','c'};
String s2=new String(values);//触发String类的构造函数:String(char[] values)
String s22=new String(values);//触发String类的构造函数:String(char[] values)
创建String对象的方式二:此种创建方式不仅写法简单,效率还高,字符串存在堆内存中的常量池
效果:如果第一次创建,会正常放入常量池。但第二次创建就不会在常量池里新建了,使用的是之前创建好的值
String s3="abc";
hashCode(),toString()和equals()
hashCode()默认实现:根据对象的地址值生成一个唯一的哈希码值
重写后:根据传入的属性值生成哈希码
toString()默认实现:打印对象的【类名@十六进制的哈希码值】
重写后:Student自定义类打印的是类型+所有属性和属性值
equals()默认实现:比较两个对象的地址值,默认使用==比较
重写后:比较的是两个对象的类型+所有属性和属性值
综上:如果执行效果与Object的默认效果不同,说明子类重写了该方法
常用String方法
hashCode() 返回此字符串的哈希码
返回值:int
equals(Object anObject) 将此字符串与指定的对象比较,比较的是重写后的串的具体内容
返回值:boolean
toString() 返回此对象本身(它已经是一个字符串!)
返回值:String
length() 返回此字符串的长度
返回值:int
toUpperCase() 所有字符都转换为大写
返回值:String
toLowerCase() 所有字符都转换为小写
返回值:String
startsWith(String prefix) 测试此字符串是否以指定的元素开头
返回值:boolean
endsWith(String suffix) 测试此字符串是否以指定的字符串结束
返回值:boolean
charAt(int index) 返回指定索引/下标处的 char 值/字符
返回值:char
indexOf(String str) 返回指定字符在此字符串中第一次出现处的索引
返回值:int
lastIndexOf(String str) 返回指定字符在此字符串中最后一次出现处的索引
返回值:int
concat(String str) 将指定字符串连接/拼接到此字符串的结尾,注意:不会改变原串
返回值:String
split(String regex) 根据给定元素来分隔此字符串
返回值:String[]
trim() 返回去除首尾空格的字符串
返回值:String
getBytes() 把字符串存储到一个新的 byte 数组中
返回值:byte[]
substring(int beginIndex) 返回一个新子串,从指定下标处开始,包含指定下标
返回值:String
substring(int beginIndex, int endIndex) 返回一个新子串,从执定下标开始,到结束下标为止,但不包含结束下标
返回值:String
String valueOf(int i) 把int转成String
返回值:String
/*本类用于测试String类的常用方法*/
public class TestString2 {
public static void main(String[] args) {
//1.创建字符串方式1--常量池中,
String s1="abc";
//1.2创建字符串方式2--堆中,new一次,创建一个对象
char[] c={'a','b','c'};
String s2=new String(c);
//1.3打印查看创建好的两个字符串
System.out.println(s1);
System.out.println(s2);
//2.测试常用方法
/*String也重写了hashCode(),根据字符串的具体内容生成哈希码值
* 虽然s1与s2的地址值不同,但是生成的哈希码值一致*/
System.out.println(s1.hashCode());//重写了
System.out.println(s2.hashCode());
System.out.println(s1.equals(s2));//true,比较的是两个字符串的内容
System.out.println(s1.toString());//abc 不推荐
System.out.println(s1);//abc
System.out.println(s1.length());//3 查看当前字符串的长度
System.out.println(s1.toUpperCase());//ABC 将本字符串转为全大写
System.out.println(s1.toLowerCase());//abc 将本字符串转为全小写
System.out.println(s1.startsWith("a"));//true 判断当前字符串是不是以a开头
System.out.println(s1.endsWith("a"));//false 判断当前字符串是不是以a结尾
System.out.println(s1.charAt(0));//a 根据下标获取字符串指定位置上的字符
String s3="abcbdbdsad";
System.out.println(s3.indexOf("b"));//1 获取指定字符第一次出现的下标
System.out.println(s3.lastIndexOf("b"));//5 获取指定字符最后一次出现的下标
System.out.println(s2.concat("cxy"));//abccxy 拼接字符串
System.out.println(s2);//abc 注意:不会改变原串s2
String s5=" hhh hh ";
System.out.println(s5.trim());//hhh hh,用于去除字符串首尾两端的空格
String s6="abcdefh";
System.out.println(s6.substring(3));//defh,从指定下标出截取子串[3,结束]
System.out.println(s6.substring(3,6));//def,从指定下标截取子串[3,6)含头不含尾
String s7="fafbfcfdfef";
String[] fs = s7.split("f");//以指定的字符f分割字符串s7
System.out.println(Arrays.toString(fs));
System.out.println(String.valueOf(10));//10
System.out.println(String.valueOf(10)+10);//1010,将int类型的参数10转为String类型的“10”
System.out.println(20+10);//30
System.out.println("20"+10);//2010
byte[] bytes = s2.getBytes();//将字符串转为byte类型的数组
System.out.println(Arrays.toString(bytes));
}
}