final修饰类/关键字
翻译为最终
可以修饰的内容:
1.类
2.方法
3.类中的成员变量
针对1:
在类的定义上使用final,表示最终类,太监类,不能继承,没有子类
定义类,功能非常完美了,不打算让子类进行扩展
最终类可以继承其他类,使用最终类创建对象,调用方法和final无关
针对2:
定义在方法的声明上,使用关键字final
最终方法
不能被子类重写
方法中的局部变量:final修饰局部变量,一次赋值终生不变,看成常量;final修饰引用类型变量,切记:final修饰引用变量,指的是引用类型保存的内存地址不能改。
针对3:
final修饰成员变量
类中的变量有默认值的
int–0
double–0.0
String扩展–null
boolean–false
char–‘|u0000’
final修饰符,固定的不是变量的默认值,一次赋值,直接=赋值,或者使用构造方法。
final修饰的成员变量,不能使用set方法赋值
构造方法:
作用,创建对象的,为对象中的数据初始化赋值
构造方法在创建对象的过程中
set方法:
set方法赋值,先把对象创建好
set方法运行的时机,是对象已经创建完毕
final关键字:编译成功后出现.class文件,class文件中是没有final的
public class Person {
final String name;
public Person() {
this.name = "张三";
}
}
public class Test {
public static void main(String[] args) {
Person p = new Person();
System.out.println(p.name);//打印出张三
}
}
------------------------------------------------------
static关键字
01
static修饰符,静态
静态中的成员,变量还是方法
在内存方法区中存在,属于自己的类
和对象无关,是对象的共享数据
名词:
static修饰成员属于类,成员成为类成员
没有static修饰成员对象,对象数据
静态成员,多了一种调用方法:
类名.成员名(推荐使用类名调用)
静态成员是对象的共享数据
非静态成员属于对象,只能被对象调用
public class Student {
String name;//学生姓名
int age;//学生年龄
static String classname="13134班";//所在班级
}
public class Test {
public static void main(String[] args) {
//类名直接调用静态成员
System.out.println(Student.classname);//打印出13134班
Student s1 = new Student();
s1.name="张三";
s1.age=18;
s1.classname="黑马363";
Student s2 = new Student();
s2.name="李四";
s2.age=20;
s2.classname="白马363";//classname是共享的,相当于重新赋值
System.out.println(s1.name+s1.age+s1.classname);
System.out.println(s2.name+s2.age+s2.classname);
}
}
02
静态使用的注意事项
静态方法中,不能直接使用非静态成员(非静态是可以引用静态的)
原因:
静态生命周期:优先于非静态的对象,存在于内存中(先人)
非静态生命周期:跟随对象,存在于内存中(后人)
静态成员方法中,不能写this,不能写super
public class Student {
//对象变量,属于对象,非静态
String name;
//下面是非静态
public void eat(){
System.out.println(name+className);
}
//类变量,属于类,所有对象的共享,静态
static String className="363";
//创建静态方法
public static void sleep(){
//System.out.println(name+className);//报错了,因为不能直接使用非静态成员
System.out.println(className);
}
}
public class Test {
public static void main(String[] args) {
//非静态
Student student = new Student();
student.name="张三";
student.eat();
//静态
Student.sleep();
}
}
03
静态的调用问题
同一个类中,调用本类的方法,可以忽略类名不写(以前的时候)
静态可以修饰成员变量和成员方法
写程序的时候,什么时候定义静态成员变量,什么时候定义静态成员方法?
具体问题具体分析:当你分析事物,分析出事物之间的共享数据和特有数据,共享数据用静态修饰,特有数据也就是对象自己,用非静态修饰.
静态方法:当方法中没有使用过非静态成员的时候,方法就应该写成静态
public class Test {
public static void main(String[] args) {
//以前的
System.out.println(getSum(1,1));
//静态
// 类名.方法名
System.out.println(Test.getSum(1,2));
}
public static int getSum(int a,int b){
return a+b;
}
}
04
代码块:静态代码块;构造代码块;局部代码块.
静态代码块:
卸载类成员位置,static(),只运行一次,只要使用了该类成员,就运行且就一次.
数据库mysql中,java操作数据库中的数据,需要加载驱动包(类),一次即可,可以反复操作数据.
构造代码块:
写在类成员位置,无用
局部代码块:更无用
静态导入:导入包,必须到导入到类的成员位置,成员必须是静态的.
public class Student {
//构造代码块
{
System.out.println("构造代码块");
}
//静态代码块
static {
System.out.println("静态代码块");
}
static int a=1;
}
public class Test {
public static void main(String[] args) {
System.out.println(Student.a);
}
}
05
多态成员的编译运行:
静态成员变量:编译运行都是父类
静态成员方法:编译运行都是父类
非静态的方法:编译是父类,运行是子类
原因:对象的多态性,static不属于对象,内存早于对象
------------------------------------------------------
String方法的扩展
public class StringDemo {
public static void main(String[] args) {
method_5();
}
/**
* String扩展[] split(字符串)切割字符串,返回数组
*/
public static void method_7(){
String[]str="ab cd ed rf dd ss".split(" +");
for (int i = 0; i < str.length; i++) {
System.out.println(str[i]);
}
}
/**
* int lastIndexOf(char ch)找字符,在字符串中最后一次出现的索引
*
*/
public static void method_6(){
int num="how do you do".lastIndexOf('d');
System.out.println(num);
}
/*
* byte[] getBytes()字符串变成数组,单个蹦出来的,因为遍历的原因
*/
public static void method_5(){
byte[]bytes="abcd".getBytes();
for (int i = 0; i < bytes.length; i++) {
System.out.println(bytes[i]);
}
}
/**
* boolean equalsIgnoreCase(String str)
* 比较字符串,不考虑大小
*/
public static void method_4(){
boolean b="abc".equalsIgnoreCase("ABC");
System.out.println(b);
}
/**
* int compareTo(String str) 字典顺序比较字符串
* a b c d 1234
*
* str1.compareTo(str2); str1和str2比较
* 调用者小于str2 结果是负数 < 0
* 调用者大于str2 结果是正数 > 0
* 调用者等于str2 结果是0
*/
public static void method_3(){
String str1="abc";
String str2="aac";
int num=str1.compareTo(str2);
System.out.println(num);
}
/**
* String(char[] bytes)
* String(char[] bytes,int 开始索引,int 个数)
*/
public static void method_2(){
char[] ch= {'a','b','c','d'};
String str = new String(ch);
System.out.println(str);
}
/**
* String(byte[] bytes)
* String(byte[] bytes,int 开始索引,int 个数)
* 97 a
* 122 z
*
* 65 A
* 90 Z
*
* 48 0
* 57 9
*/
public static void method_1(){
byte[] bytes = {100,101,102,103,104};
String str = new String(bytes,1,2);
System.out.println(str);
}
}
------------------------------------------------------
内部类
01
访问内部类(InnerClass)公式
类:分析事物的时候,具体的事物,定义为类
一个具体的事物的里面,包含了另一个具体的事物
举例:
车是一个事物,事物里面还有一个事物,引擎(发动机)
车是一个类,发动机也是一个,车是外部的类,发动机是车的内部的类
class A{
class B{}
}
A是B的外部类,B是A的内部类
内部类可以直接使用外部类成员,包括私有
外部类使用内部成员,创建出内部类对象
成员内部类:类定义在一个类的成员位置
局部内部类:类定义在一个方法中
/**
* Outer类,外部类
* 成员内部类
*/
public class Outer {
//成员位置,定义类,内部类
class Inner{
public void inner(){
System.out.println("内部类方法");
}
}
/* public void out(){
//创建内部类的对象,调用方法
Inner inner = new Inner();
inner.inner();
}*/
}
public class Test {
public static void main(String[] args) {
// Outer outer = new Outer();
// outer.out();
//访问内部类方法的公式
//外部类名.内部类名 变量名=new 外部类对象.new内部类对象();
Outer.Inner oi = new Outer().new Inner();
oi.inner();
}
}
02
访问特点
public class Outer {
int a=3;//外部类的成员变量
class Inner{
int a=2;//内部类的成员变量
public void inner(){
int a=1;//方法内部变量
System.out.println(a);
System.out.println(this.a);//内部类的成员变量
System.out.println(Outer.this.a);//外部类的成员变量
}
}
}
/*
* 内部类访问特点
* */
public class Test {
public static void main(String[] args) {
Outer.Inner oi=new Outer().new Inner();
oi.inner();
}
}
03
局部内部类
public class Outer {
//定义方法
public void out(){
//方法体里面,定义类,局部的内部类
class Inner{
//定义局部内部类的方法,这里面不能用静态方法,因为非静态内部类中不能使用静态方法,以及非静态变量。
public void inner(){
System.out.println("局部内部类的方法");
}
}
//创建内部类对象
Inner inner = new Inner();
inner.inner();
}
}
/*
* 局部内部类,类定义在方法中
* */
public class Test {
public static void main(String[] args) {
//调用方法inner()
Outer outer = new Outer();
outer.out();
}
}
04
匿名内部类
内部类,出现在方法中的内部类
匿名,没有名字
减少书写,减少的是继承父类或者接口
使用前提,必须有继承或者接口出现
伪代码
class MyInterfaceImpl implements MyInterface{
public void inter(){
System.out.println();
}
}
测试:创建实现类对象
MyInterface my = new MyInterfaceImpl();
my.inter();
以上程序的步骤:
1.定义接口实现类
2.实现类重写方法
3.创建实现类对象
匿名内部类:简化的是实现类实现接口
重写方法,创建对象
格式:
new 父类或者接口(){
抽象方法的重写
};
专业上称为匿名内部类
格式是在创建接口实现类的对象
public interface MyInterface {
public abstract void inter();
}
public class Test {
public static void main(String[] args) {
/**
* new 父类或者接口(){
* 抽象方法的重写
* };
* 格式是在创建接口实现类的对象
* 使用实现类对象直接调用方法
*/
//new 接口
new MyInterface(){
//重写抽象方法
public void inter(){
System.out.println("实现类重写方法");
}
}.inter();
}
}
05
重写多个
public interface MyInterface {
public abstract void inter();
public abstract void inter2();
}
/**
* 使用匿名内部类的形式
* 创建接口的实现类对象,并调用方法
* inter(),inter2()
*/
public class Test {
public static void main(String[] args) {
/*
* new 父类或者接口(){
* 抽象方法的重写
* };
*
* 并调用方法
*
* class xxx implements MyInterface{
* 重写方法
* 重写方法2
* }
* MyInterface my = new XXX();
* my.方法();
* my.方法2();
*
*
* 匿名内部类,就是接口实现类对象
* */
MyInterface my= new MyInterface() {
@Override
public void inter() {
System.out.println("实现类重写方法");
}
@Override
public void inter2() {
System.out.println("实现类重写方法222");
}
};
my.inter();
my.inter2();
}
}
------------------------------------------------------
方法的参数
public abstract class Animal {
public abstract void eat();
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public interface MyInterface {
void inter();
}
public class MyInterfaceImpl implements MyInterface {
@Override
public void inter() {
System.out.println("实现类重写方法");
}
}
public class Student {
String name;
}
/**
* 方法的参数:
*
* public void xxx (参数列表){}
* 参数列表可以是基本数据类型,也可以是引用数据类型
*/
public class Test {
public static void main(String[] args) {
//调用方法setStudent,传递对象
// Student student = new Student();
setStudent( new Student() );
//调用方法setAnimal,传递他的子类对象
setAnimal( new Cat() );
//调用方法setMyInterface,传递接口实现类对象
setMyInterface( new MyInterfaceImpl() );
}
/**
* 创建方法:
* 要求方法的参数是引用数据类型 MyInterface
* MyInterface是接口
* 调用方法,传递接口实现类对象
*/
public static void setMyInterface(MyInterface my){
my.inter();
}
/**
* 创建方法:
* 要求方法的参数是引用数据类型Animal
* Animal是抽象类
* 方法的参数是抽象类类型,调用者调用方法
* 必须传递他的子类对象
*/
public static void setAnimal(Animal animal){
animal.eat();
}
/**
* 创建方法:
* 要求方法的参数是引用数据类型Student
* 调用方法,请传递 Student的对象
*/
public static void setStudent(Student student){
//student操作成员变量
student.name = "张三";
System.out.println(student.name);
}
}
------------------------------------------------------
方法的参数升级版
01
/**
* 方法的返回值
* 方法运行后的结果,结果的数据类型
* 返回值可以是基本类型,也可以是引用数据类型
*/
public class Test {
public static void main(String[] args) {
//调用方法getStudent(),返回Student对象
Student student = getStudent();
System.out.println(student.name);
//调用方法 getAnimal(),返回Animal类型
Animal animal=getAnimal();
animal.eat();
//调用方法getMyInterface()接收返回值,接口类型
MyInterface my = getMyInterface();
my.inter();
}
/**
* 创建方法:返回值是引用类型
* 返回是MyInterface类型,接口
* 方法中 return语句,必须返回接口实现类对象
*/
public static MyInterface getMyInterface(){
return new MyInterfaceImpl();
}
/**
* 创建方法:返回值是引用类型
* 返回的是Animal类型,是抽象类
* 方法中 return语句,必须返回抽象类的子类对象
*/
public static Animal getAnimal(){
return new Cat();
}
/**
* 创建方法: 返回值类型是引用类型
* Student,返回值类型写Student
* 方法返回值,return 语句必须返回Student对象
*/
public static Student getStudent(){
// Student student = new Student();
return new Student();
}
}
02
返回值是抽象类
public abstract class Animal {
/**
* 抽象类,定义带有方法体的方法
* 方便调用定义为静态修饰
* 返回值,必须return 返回子类对象
*/
public static Animal getAnimal(){
return new Cat();
}
public abstract void eat();
}
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
/**
* 方法的返回值是抽象类
*/
public class Test {
public static void main(String[] args) {
/**
* 获取子类Cat类对象
* 对象不是自己new的,而是通过方法来获取
* 方法定义在了父类中
*
* 无子类现身,方便调用者
*
* 日历对象
* new 日历对象() 语言,时区
*/
Animal animal=Animal.getAnimal();
animal.eat();
}
}
------------------------------------------------------
权限修饰符
/**
* Java语言四大权限 JDK8以前
*
* public公共 protected受保护 default默认 private私有
* 同一个类 Ok OK OK OK
* 同一个包 OK OK OK NO
* 不同包子类 OK OK NO NO
* 不同包不是子类 OK NO NO NO
*
* 受保护权限 protected 给子类使用
* super.调用
*/