final关键字
final是java中的一个关键字
final用于变量声明,被声明的变量的值将无法改变
子类能继承超类,能对超类的功能进行拓展,如果不希望子类对超类进行拓展 可以给超类加final关键字,这样子类就无法继承超类了
final修饰的类无法被继承
final class A{
}
class B extends A{
}
//java: 无法从最终A进行继承
final也可以修饰变量;
public static void main(String[] args) {
final double pi=3.14;
pi=2.5;
System.out.println(pi);
}
//java: 无法为最终变量pi分配值
如果被final修饰的是一个引用也不能二次赋值
但可以利用类中的方法去改变类中的变量
class A{
int a;
public A() { }
public int getA() {return a;}
public A(int a) { this.a = a; }
public void fu(int a) { this.a=a; }
}
public class jihuo{
public static void main(String[] args) {
final A a=new A(10);
a.fu(20);
a=new A(5);//报错
}
}
//java: 无法为最终变量a分配值
超类中被final修饰的方法无法被子类重写和覆盖
class A{
public final void printl()
{
System.out.println("jykglyu");
}
}
class B extends A{
public void printl()
{
System.out.println("rdyt");
}
}
//java: B中的printl()无法覆盖A中的printl()
//被覆盖的方法为final
补充:超类调用子类的方法 需要向下转型
class A{
public void printl()
{
System.out.println("jykglyu");
}
}
class B extends A{
public void domel()
{
System.out.println("hello world");
}
}
public class jihuo{
public static void main(String[] args) {
A a=new B();
//a.domel();
//报错
if(a instanceof B)
{
B b1=(B)a;
((B) a).domel();
b1.domel();
}
}
}
补充:当类中的变量没有初始化时,类中的构造函数会将变量默认设置为0;但加了final的变量不能被构造函数初始化
错误
class A{
int country;
public int getCountry() { return country; }
}
public class jihuo{
public static void main(String[] args) {
A a=new A();
System.out.println(a.getCountry());
}
}
错误
class A{
final int country;
public int getCountry() { return country; }
}
public class jihuo{
public static void main(String[] args) {
A a=new A();
System.out.println(a.getCountry());
}
}
所以程序员必须手动初始化final定义的变量
抽象类
在普通类的基础上扩充了一些抽象方法(0~n)的类(抽象类是普通类的超集),使用abstract关键字定义。
抽象类不能直接产生实例化对象,因为抽象类是“半成品”,无法直接使用。不能直接new。
抽象类abstract不能与final一起使用。
抽象类的子类可以是抽象类也可以是普通类。
抽象方法:使用abstract 关键字定义并且没有方法体的方法。抽象方法必须在抽象类中,但抽象类中可以没有抽象方法。
抽象类中的抽象方法不能有主体
abstract class A{
public abstract void move(){}
}//报错
//java: 抽象方法不能有主体
一个非抽象类继承抽象类必须覆盖抽象类中的抽象方法,或者将子类改为抽象类
abstract class A{
public abstract void move();
}
class B extends A{
//public void move(){}
}
//报错
//java: B不是抽象的, 并且未覆盖A中的抽象方法move()
在主函数中可以通过父类型引用指向子类型对象
A a=new B();
a.move();
如果B 也是抽象类 那么就可以不用重写A中的方法
一道面试题:java中没有方法体的方法都是抽象方法(T/F)
答案:F
解释:例如Object类中就有很多方法没有方法体,但他们多不是抽象方法,例如:public native inthashCode();这个方法是调用C++写的动态链接库程序。前面没有abstract。有一个native,表示调用JVM本地程序。
接口
接口基础语法
接口也是一种“引用数据类型”。编译之后也是一个字节码文件
接口是完全抽象的。是一种特殊的抽象类。
接口支持多继承,一个抽象类支持继承多个父类
接口中包含两部分,一部分是常量,一部分是抽象方法
接口中的方法不能有方法体
public class text1 {
public static void main(String[] args) {
System.out.println(A.PI);//调用接口中的变量,接口中的变量不能改变
}
}
interface C extends A,B{//一个接口支持多继承
public static final double PI=3.1415926;//接口中常量可以省略public static final
public abstract int moth();//方法名可以省略public abstract
}
package Interface;
public class text2 {
public static void main(String[] args) {
FoudMenu cooker=new AmerCook();
Custermor custermor=new Custermor(cooker);
custermor.redor();
FoudMenu cooker1=new ChinaCook();
Custermor custermor1=new Custermor(cooker1);
custermor1.redor();
}
}
class ChinaCook implements FoudMenu {
public void xhscjd(){
System.out.println("我是中餐厨师我会西红柿炒鸡蛋");
}
public void yxrs()
{
System.out.println("我是中餐厨师我会做鱼香肉丝");
}
}
class AmerCook implements FoudMenu{
public void xhscjd(){
System.out.println("我是西餐厨师我不会西红柿炒鸡蛋");
}
public void yxrs()
{
System.out.println("我是西餐厨师我不会做鱼香肉丝");
}
}
class Custermor{
private FoudMenu foodmenu;
public Custermor(){ }
public Custermor(FoudMenu foodmenu)
{
this.foodmenu=foodmenu;
}
public void setFoodmenu(FoudMenu foodmenu){
this.foodmenu=foodmenu;
}
public FoudMenu getFoodmenu(){
return this.foodmenu;
}
public void redor(){
foodmenu.xhscjd();
foodmenu.yxrs();
}
}
interface FoudMenu{
void xhscjd();
void yxrs();
}
抽象类与接口的区别
类与类之间叫继承,类与接口之间叫做实现
继承使用extends,实现使用implements关键字
接口是一个抽象概念,
可插拔性
package Interface;
public class text2 {
public static void main(String[] args) {
Flyable f=new Cat();
f.fly();
Flyable f1=new Snake();
f1.fly();
Flyable f2=new Pig();
f2.fly();
}
}
interface Flyable{
void fly();
}
class Animal{}
class Cat extends Animal implements Flyable{
public void fly()
{
System.out.println("我是一只神奇的星猫");
}
}
class Snake extends Animal implements Flyable{
public void fly(){
System.out.println("我是一条蛇,我不会飞");
}
}
class Pig extends Animal implements Flyable{
public void fly()
{
System.out.println("我是一只猪,我想飞");
}
}
/*我是一只神奇的星猫
我是一条蛇,我不会飞
我是一只猪,我想飞*/
补充:
1.一个类可以实现多个接口,与之相反一个类只能继承一个父类
2.接口结合多态使用才能降低程序的耦合度
3.(is a)继承,(has a)关联,(like a)实现
抽象类是半抽象的。
接口是完全抽象。
抽象类中有构造方法。
接口中没有构造方法。
类与类之间只能单继承。
接口与接口之间支持多继承。
接口中只存在常量与
package和import
package出现在java源文件的第一行
一个Java源代码程序就是一个编译单元,每个编译单元都必须有一个后缀名.java,而在编译单元内有且仅有一个public类,否则编译器就不会接受。该public类的名称必须与文件的名称相同(包括大小写,但不包括后缀名.java)
假设文件名称TelephonyManager,就有一个公共类TelephonyManager
访问控制权限
访问控制权限可以修饰什么
属性(四个都可以)
方法(四个都可以)
类(只能由public和默认修饰,其他的不行 )
接口(只能由public和默认修饰,其他的不行)
Object类
JDK类库的根类是Object
当使用equals()时默认比较的是内存地址;
在java中字符串和引用数据类型的比较一般采用equals()
System.out.println("b" == "b"); //true
System.out.println("a".equals("a")); //true
System.out.println("a".equals(new String("a"))); //true
System.out.println("a" == new String("a")); //false
System.out.println(new String("a") == new String("a")); //false
System.out.println(new String("a").equals(new String("a"))); //true
数据类型的比较采用“==”
以后所有类的equals()方法需要重写,因为Object中的equals()方法比较的是两个对象的内存地址,我们一般会比较内容,所以需要重写,如下所示
package Objecttext;
import java.util.TreeMap;
public class text {
public static void main(String[] args) {
Mytext t = new Mytext();
Mytext t1 = new Mytext();
String s = t.toString();
System.out.println(s);
System.out.println(t1 == t);
System.out.println(t1.equals(t));
}
}
class Mytext {
int id = 1000;
int age = 55;
String name = "hvhvhjvjuyyswsyiuliuts";
public Mytext() {}
public Mytext(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {return id;}
public void setId(int id) {this.id = id;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
@Override
public String toString() {
return "Mytext{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
public boolean equals(Object obj) {
int id = this.id;
int age = this.age;
String name = this.name;
if (obj instanceof Mytext) {
Mytext t = (Mytext) obj;
int id1 = t.id;
int age1 = t.age;
String name1 = t.name;
if (id == id1 && age == age1 && name == name1) {
return true;
}
} return false;
}
}
//输出
//Mytext{id=1000, age=55, name='hvhvhjvjuyyswsyiuliuts'}
//false
//true
基本数据类型的比较使用“==”;
对象与对象的比较使用equals();
object中equals重写并对两个相同的对象进行比较
package Objecttext;
public class text01 {
public static void main(String[] args){
User u1=new User("zhangsan",new Address("bjs","dxq","356856"));
User u2=new User("zhangsan",new Address("bjs","dxq","356856"));
User u3=new User("LiShi",new Address("bjs","dxq","356856"));
System.out.println(u1.equals(u3));
System.out.println(u1.equals(u2));
}
}
class User
{
String name;
Address addr;
public User() {}
public User(String name, Address addr) {
this.name = name;
this.addr = addr;
}
public boolean equals(Object obj)
{
if (obj==null||!(obj instanceof User))
return false;
if (this==obj)
return true;
User u=(User)obj;
if (this.name.equals(u.name)&&this.addr.equals(u.addr))
{
return true;
}
return false;
}
}
class Address{
String city;
String street;
String zipcode;
public Address(){}
public Address(String city, String street, String zipcode) {
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
public boolean equals(Object obj )
{
if (obj==null||!(obj instanceof Address))
return false;
if (this==obj)
return true;
Address a=(Address)obj;
if (this.city.equals(a.city)&&this.street.equals(a.street)&&this.zipcode.equals(a.zipcode))
return true;
return false;
}
}
//结果返回true
关于object类中的finalize()方法。
在Object类的原码中:
protected void finalize() throws Throwable{}
finalize()方法没有方法体, 里面没有代码,而且这个方法是用protected修饰的。
这个方法不需要程序员调用,jvm垃圾回收器负责调用这个方法,当一个java对象即将被垃圾回收器回收时垃圾回收器负责调用finalize()方法。
它不像equals()和toString()需要你写代码调用,finalize()只需要你重写,重写完以后自动会有程序来调用,GC调用finalize()方法
静态代码块的作用是什么?
static{}
静态代码块在类加载的时刻执行,并且只执行一次。是一个加载时机,final则是一个垃圾回收时机。
java中的垃圾回收器不轻易启动,垃圾太少或时间没到都不启动
package Objecttext;
public class text02 {
public static void main(String[] args) {
//创建对象
for (int i=0;i<1000000;i++)
{
nume f=new nume();
f=null;
System.gc();//垃圾回收器建议启动方法
}
}
}
class nume{
//重写finalize()方法
//nume类型的对象被垃圾回收器回收的时候垃圾回收器负责调用f.finzlize();
protected void finalize() throws Throwable{
System.out.println("即将被回收");
}
}
//即将被回收
//即将被回收.........
hashCode方法:
在Object中的hashCode方法是怎么样的?
public native inthashCode();
这个方法不是抽象方法,带有native,是调用底层C++程序。
hashCode返回的是哈希码:
实际上就是一个java对象的内存地址,经过哈希算法,得出的一个值。
所以hashCode()方法的执行结果可以等同于一个java对象的内存地址。
public class text03 {
public static void main(String[] args) {
Object o=new Object();
int hc=o.hashCode();
nume n=new nume();
int hs=n.hashCode();
System.out.println(hc);
System.out.println(hs);
}
}
class nump{
}
匿名内部类
普通接口实现加法计算
public class Main {
public static void main(String[] args) {
// write your code here
mymath m=new mymath();
comp c=new Compler();
m.mysun(c,1,3);
}
}
interface comp{
int sum(int x,int y);
}
class Compler implements comp{
public int sum(int x,int y){
return x+y;
}
}
class mymath
{
public void mysun(comp c,int x,int y)
{
int ret=c.sum(x,y);
System.out.println(x+" + "+y+"="+ret);
}
}
利用匿名内部类实现加法计算
public class Main {
public static void main(String[] args) {
mymath m=new mymath();
m.mysun(new comp(){
public int sum(int x,int y){
return x+y;
}
},1,3);
}
}
interface comp{
int sum(int x,int y);
}
class mymath
{
public void mysun(comp c,int x,int y)
{
int ret=c.sum(x,y);
System.out.println(x+" + "+y+"="+ret);
}
}
hashmap
双列集合
自定义的枚举需要重写hashcode和equals吗
不需要
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
//遍历map中的键
for (Integer key : map.keySet()) {
System.out.println("Key = " + key);
}
//遍历map中的值
for (Integer value : map.values()) {
System.out.println("Value = " + value);
}
比较器的使用
package test;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Arrays;
public class ClassWork {
public static void main(String[] args) {
Goods [] goods={new Goods("pg",10),new Goods("xj",5),new Goods("sg",15)};
Arrays.sort(goods);
for (Goods i:goods
) {
System.out.println(i);
}
}
}
@NoArgsConstructor
@AllArgsConstructor
@Data
class Goods implements Comparable<Goods>{
private String name;
private Integer weight;
@Override
public int compareTo(Goods o) {
if (this.weight>=o.weight)
{
return 1;
}
return -1;
}
}