内部类
概念
在一个类中书写另一个类
分类
同级类(严格意义上来讲只是一种书写形式不是内部类)
成员内部类(全局内部类)
局部内部类(包含匿名内部类)
①同级类
在使用时与普通类一致,只是访问范围只有本包下,将相当于少创建了一个文件
//员工类
public abstract class Employee {
public String name;// 姓名
public int birthdayMonth;// 生日月份
public double salary;// 薪资
public abstract void getSalary(int month);
}
// 同级类的形式
class sale extends Employee {
public double saleMoney;// 销售额
public double rate;// 提成率
@Override
public void getSalary(int month) {
salary+=saleMoney*rate;
if(birthdayMonth==month){
salary+=100;
}
System.out.println("销售员"+name+month+"月份的工资为:"+salary);
}
}
②成员内部类(全局内部类)
书写在类体中的类
修饰符 class 类名称 {
修饰符 class 类名称 {
//...
}
//...
}
public class A {
int aa;
// 成员内部类
// 在一个类中书写另一个类
public class B {
// 内部类可以随意访问外部类(包含其他外部类)
public void b() {
// 直接访问当前外部类
A a = new A();
// 可以直接访问其他外部类
A1 a1 = new A1();
int b=A.this.aa;//内部类可以直接使用外部类的属性
//由于就近原则当出现属性与外部类相同时,使用语法
//外部类.this.属性名进行指定
}
}
public void a() {
B b = new B();
b.b();
}
}
class A1 {
// 内部类的调用
public static void main(String[] args) {
// 1、间接调用
// 其他外部类不能直接访问但是书写内部类的外部类可以访问
// 在外部类声明方法创建内部类对象调用方法
// 在其他类中创建外部类调用内部类方法
A a = new A();
a.a();// 实际调用内部类b方法
// 2、直接调用
//直接在其他外部类创建内部类对象
//语法:外部类.内部类 标识符 =new 外部类().new 内部类();
A.B b=new A().new B();
//可以将内部类当做变量,如果想获取一个类的成员变量那么必须先创建这个类的对象
//之后因为是一个类 如果想使用必须创建对象
b.b();//直接使用B对象调用b方法
}
}
1、书写在类体中的类
2、只能由当前类的外部类直接访问
3、可以直接访问外部类(其他外部类)
4、使用同名外部类变量时注意语法 外部类.this.属性名
5、其他外部类访问方式 间接方式(创建外部类通过外部类方法使用内部类) 直接方式(通过外部类直接创建内部类对象)
如果类是定义在一个方法内部的,那么这就是一个局部内部类。
修饰符 class 外部类名称 {
修饰符 返回值类型 外部类方法名称(参数列表) {
class 局部内部类名称 {
//...
}
}
}
public class B {
int b = 1;
// 局部内部类
// 在方法体中定义的类
public void b() {
int b = 2;
// 由于方法中变量在方法执行结束后会释放
// 并且只能由当前方法调用,所以修饰符不能使用public
class C {
int c = 3;
public void c() {
System.out.println(c);
System.out.println(b);// 可以直接使用方法中的变量
System.out.println(B.this.b);// 通过固定语法访问同名全局变量
// 当局部内部类使用方法中的变量时,一般使用final修饰
// 由于其数据存储空间不同,在执行时可能导致错误
// 1. new 出来的对象在堆内存当中。
// 2. 局部变量是跟着方法走的,在栈内存当中。
// 3. 方法运行结束后,立刻出栈,局部变量就会立刻消失。
// 4. 但是new出来的对象在堆当中持续存在,直到垃圾回收消失。
}
}
C c = new C();
c.c();
}
public void b1() {
// 其他方法不能调用局部内部类,只能通过间接调用
}
public static void main(String[] args) {
B b = new B();
b.b();
}
}
局部内部类总结:
1、书写在方法体中的类
2、只能由当前方法直接访问
3、可以直接访问外部类(其他外部类)
4、使用同名方法所在类变量时注意语法 外部类.this.属性名(对于方法中同名属性不能直接调用建议改名)
5、其他外部类(方法)访问方式 间接方式(通过访问方法的形式进行调用)
6、局部内部类使用方法中变量的值实际过程是创建空间将值复制过来进行使用,要求变量理论不变的原因,是因为回收时机不同,可能导致程序错误(局部内部类不建议使用方法中的属性进行属性的赋值)
修饰内部类的权限
public > protected > (default) > private
定义一个类的时候,权限修饰符规则:
外部类:public / (default)
成员内部类:都可以写,public > protected > (default) > private
局部内部类:什么都不能写,但不是default
匿名内部类
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次。
那么这种情况下就可以省略调该类的定义,而改为使用【匿名内部类】。
匿名内部类用于创建子类或者实现类
接口(父类) 对象名 = new 类名或者接口名称() {
//覆盖重写所有抽象方法
};
public interface C {
void a();
void b();
void c();
}
class Test{
public static void main(String[] args) {
//匿名内部类就是省略类的声明与命名只书写类体{}
//一般用于只使用一次的子类或实现类
C c=new C(){
@Override
public void a() {
System.out.println("a");
}
@Override
public void b() {
System.out.println("b");
}
@Override
public void c() {
System.out.println("c");
}
};
//会直接使用匿名内部类创建一个唯一对象
//这个对象只有一个,因为没有类
//相当于使用类体临时创建了一个类并用其创建对象
c.a();
}
}
创建的对象只调用一次方法那么可以直接使用new 类名().方法()进行使用
注意:
匿名对象与匿名内部类不是同一个东西
匿名对象省略了类的声明
匿名内部类省略了class关键字以及类名
匿名内部类总结
1、匿名内部类由于没有创建类,所以使用父类或者接口声明变量保存遵循多态,只能使用重写的方法以及父类的属性,但是重写的方法可以使用这些属性,只不过不能通过对象进行赋值,(一般在使用匿名内部类的时候不会创建属性只重写方法)
API
概念
API全名:application(应用) programming(程序) interface(接口) API是应用程序编程接口
Java API
Java API就是sun公司提供给我们使用的类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用。 我们可以通过查帮助文档来了解Java提供的API如何使用
Object类
Object类是所有类的父类,所有类都字节或间接的继承与Object类
Object类中提供了所有类都一定拥有的方法由java决定
toString方法
将对象转换为字符串,Object类转换字符串的方法类似于打印地址
所有的类都继承于Object类所有都继承了这个方法,当进行对象的输出时默认调用该对象的toString()方法,将返回的字符串在控制台进行打印
在调用输出语句输出对象时,实际上时自动调用对象toString方法将对象转换为字符串之后进行输出
一般我们会重写这个方法,这样在进行对象输出时就会按照我们定义的方式进行输出
在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。 如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
hashCode值在对象运行过程中唯一不重复
String s1="柴柕";
String s2="柳柴";
System.out.println(s1.hashCode());//851553
System.out.println(s2.hashCode());//851553
子类如果重写equals方法那么必须重写hashCode方法
两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
equals与==的区别
1、语法上的区别
==是算术运算符 equals是方法
2、判断内容不同
==经常用于判决基本数据类型数值类型是否相等,也可以判断两个对象地址是否相等(同一对象)
equals只能判断引用数据类型
3、对于object类而言equals与==没有区别
equals默认使用==判断两对象是否相同
4、对于其他类重写equals方法而言的不同(String为例)
==判断的是两对象地址是否相同。equals判断的是两字符串对象内容是否相同
String类
引用数据类型,用于保存字符串,Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。
字符串为常量,字符串值一旦初始化便不可以修改。 常量池:在java用于保存在编译期已确定的,已编译的class文件中的一份数据。
String s = "abc";
s="bcd";
//变量s保存的是常量abc所在的地址
//当重新赋值时会将新的常量地址进行赋值
//但是原字符串abc会一直存储在常量池中直至程序运行结束
String s1="bcd";
System.out.println(s==s1);
//因为相同常量只创建一次。再次使用直接将地址进行赋值
String 可以理解为特殊的字符数组
构造方法
String() 初始化一个新创建的 String 对象,使其表示一个空字符序列。
String(byte[] bytes) 通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
String(byte[] bytes, int offset, int length) 通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。
String(char[] value, int offset, int count) 分配一个新的 String,它包含取自字符数组参数一个子数组的字符。
String(String original)
String s1=new String();//等价String s1="";
String s11=new String();
//由于使用new关键字创建的新对象虽然存储字符串相同但地址不同
//原因:对象存储数据为位置与常量存储位置不同
//System.out.println(s1==s11);
byte b[]={65,66,67,68};
String s2=new String(b);
//将数值对应字符编码进行转换之后连接
System.out.println(s2);//ABCD
String s3=new String(b,1,2);
//使用数组部分数据从索引1开始之后的2位数据
System.out.println(s3);//BC
char c[]={'a','b','c','d'};
String s4=new String(c);
System.out.println(s4);
String s5=new String(c,0,2);
System.out.println(s5);
String str1="hello";
String str2=" world!";
String str3="hello world!";
String str4=str1+str2;
String str5="hello"+" world!";
System.out.println(str3==str5);//true
System.out.println(str4==str5);//false
常用方法
charAt(int index) 返回指定索引处的 char 值。
indexOf(String ch) 返回指定字符在此字符串中第一次出现处的索引。
isEmpty() 当且仅当 length() 为 0 时返回 true。
lastIndexOf(String ch) 返回指定字符在此字符串中最后一次出现处的索引。
length() 返回此字符串的长度。
replace(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
split(String regex, int limit) 根据匹配给定的正则表达式来拆分此字符串。
startsWith(String prefix) 测试此字符串是否以指定的前缀开始。
toLowerCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
String toUpperCase() 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
contains(CharSequence s) 当且仅当此字符串包含指定的 char 值序列时,返回 true。
将指定字符串连接到此字符串的结尾
String str="abcdefgc";
// charAt(int index)
// 返回指定索引处的 char 值。
//String底层使用char数组进行数据存储所以可以直接返回某一索引数据
char charAt = str.charAt(0);
System.out.println(charAt);//a
// indexOf(String ch)
// 返回指定字符在此字符串中第一次出现处的索引。
int indexOf = str.indexOf("c");
System.out.println(indexOf);//2
// lastIndexOf(String ch)
// 返回指定字符在此字符串中最后一次出现处的索引。
int lastIndexOf = str.lastIndexOf("c");
System.out.println(lastIndexOf);//7
// isEmpty()
// 当且仅当 length() 为 0 时返回 true。
//判断字符串是否为空字符串""
boolean empty = str.isEmpty();
System.out.println(empty);
// length()
// 返回此字符串的长度。
//返回存储数组的长度
int length = str.length();
System.out.println(length);//8
// replace(char oldChar, char newChar)
// 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String replace = str.replace("c", "CC");
System.out.println(replace);//abCCdefgCC
// split(String regex)
String[] split = str.split("c");
//以指定字符进行字符串截取返回字符串数组
for (int i = 0; i < split.length; i++) {
System.out.print(split[i]+" ");
}
System.out.println();
// startsWith(String prefix)
// 测试此字符串是否以指定的前缀开始。
boolean startsWith = str.startsWith("abc");
System.out.println(startsWith);
// String toUpperCase()
// 使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
String upperCase = str.toUpperCase();
System.out.println(upperCase);
// toLowerCase()
// 使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
String lowerCase = upperCase.toLowerCase();
System.out.println(lowerCase);
// contains(CharSequence s)
// 当且仅当此字符串包含指定的 char 值序列时,返回 true。
boolean contains = str.contains("cdef");
System.out.println(contains);
//String很多方法会返回新的字符串
//因为String存储的是常量 不允许修改,所以只能产生新的字符串保存结果
//不会修改原字符串数据
//但是会加大程序的负担
System.out.println(str);
总结:
1、String存储字符串常量不允许更改
2、String返回新的字符串不会修改本身
4、String本质是字符数组
练习
1:String s1 = new String(“abc”);String s2 = “abc”;有区别吗?
2:String s1 = "abc";String s2 = "abc"; System.out.println(s1==s2);? String s3 = new String("abc");String s4 = new String("abc"); System.out.println(s3==s4);?
3:String s = "helloworld"; String s2 = "hello"; String s3 = "world"; System.out.println(s == "hello"+"world"); System.out.println(s == s2+s3);
4:使用字符数组分别实现String中
lastIndexOf方法
split方法
endsWith方法
concat方法
扩展:
1:遍历字符串中每一个字符。
2:将一个int数组的值拼写成字符串形式。
3:给定一个字符串找到子串在字符串中出现的 次数。String s = "abcitcastabcxxxabc"中的"abc"
注意:本文归作者所有,未经作者允许,不得转载