三大特性
封装
public class Girl {
private int age;
//读取年龄
public int getAge(){
return age;
}
//设置年龄
public void setAge(int age){
if(age>=30){
this.age=18;
}else{
this.age=age;
}
}
}
public class Test {
public static void main(String[] args) {
Girl g=new Girl();
g.setAge(33);
g.getAge();
System.out.println(g.getAge());//输出18
}
}
对于定义的构造器,如果修改了get set方法,那么构造器内部也需要修改
继承
extends 关键字
ublic class Person {
//属性
private int age;
private String name;
private double hight;
//getter-setter方法
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;
}
public double getHight() {
return hight;
}
public void setHight(double hight) {
this.hight = hight;
}
//方法
public void eat(){
System.out.println("eat");
}
public void sleep(){
System.out.println("sleep");
}
public void yell(){
System.out.println("yell");
}
}
public class Student extends Person{//子类Student继承 父类 Person
//属性
private int sno;
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
//方法
public void study(){
System.out.println("study");
}
}
权限修饰符
default:缺省修饰符,不写就行 :权限到同一个包的其他类都可以访问
方法的重写
重载和重写的区别
重写的返回值只有在引用数据类型是才是,基本数据类型不可以
super关键字
生成构造器可以使用alt+insert快捷键
继承条件下,构造方法是怎样执行的
Object类
toString()方法
IDEA快捷键重写toString()
equals()方法
instanceof 运算符或者关键字
快捷键生成equals
???向下转型,为了获取子类中特有的内容
object obj=new phone();
类和类的关系
package relationship;
public class girl {
//属性
String name;
double weight;
mom m;//将一个类作为另一个类的属性
//mom m=new mom();
//方法
public void love(boy b){//将一个类作为另一个类中的方法的形参
System.out.println("in love with "+b.name);
b.buy();
}
public void wechat(){
m.say();
}
//构造器
public girl(String name,double weight) {
this.name = name;
this.weight=weight;
}
}
package relationship;
public class boy {
//属性
String name;
int age;
//方法
public void buy(){
System.out.println("buybuybuy");
}
//构造器
public boy(String name, int age) {
this.name = name;
this.age = age;
}
}
package relationship;
public class mom {
public void say(){
System.out.println("listen to mom");
}
}
package relationship;
public class test {
public static void main(String[] args) {
boy tom=new boy("tom",19);
girl lili=new girl("lili",99.9);
lili.love(tom);
lili.m=new mom();//引用数据类型先初始化才能调用
lili.wechat();
}
}
类和类之间的关系:继承;实现;依赖(形参);关联(属性);聚合(属性);组合(属性)
多态
两种应用场景:父类做形参;父类做返回值
多态与属性无关,多态指的是方法的多态,而不是属性的多态
父类—》子类:继承
子类—》父类:泛化
package duotai;
public class animal {
int age;
public void shout(){
System.out.println("animal");
}
}
package duotai;
public class cat extends animal {
public void shout(){
System.out.println("cat");
}
}
package duotai;
public class dog extends animal{
public void shout(){
System.out.println("dog");
}
}
package duotai;
public class pig extends animal{
double weight;
public void shout(){//重写父类animal的shout方法
System.out.println("pig");
}
public void eat(){
System.out.println("pig eat");
}
}
package duotai;
public class girl {
public void play(animal an){
an.shout();//一个方法就够,这就是多态,不然要写跟猪狗猫玩的方法重载
}
}
package duotai;
public class test {
public static void main(String[] args) {
girl g=new girl();
dog d=new dog();
pig p=new pig();
animal an=d;//多态
g.play(an);//输出dog
cat c=new cat;//合并animal an2=new cat();
animal an2=c;
g.play(an2);//输出cat
animal an3=p;
g.play(an3);//输出pig
pig p2=(pig)an3;//向下转型,是因为an只能访问animal中的东西,不能访问pig中的东西,转型之后才能访问
p2.weight=60.8;
p2.shout();//输出pig
p2.eat();//输出 pig eat
}
}
注意:多态可以提高扩展性,但是扩展性没有达到最好,以后我们会学习反射
多态与属性无关,与方法有关
左侧=编译期类型,右侧=运行期类型
内存分析
向上转型,向下转型
简单工厂设计模式
package duotai;
public class petStore {//----》工厂类
//方法:提供动物
public static animal getAnimal(String petName){//加上static就可以用类名.方法名调用,
//没加static就必须创建一个petStore对象然后通过对象.方法名调用
animal an=null;//局部变量必须进行初始化
if("cat".equals(petName))//petName.equals("cat")--->这样写容易发生空指针异常
{
an=new cat();
}
if("dog".equals(petName)){
an=new dog();
}
return an;//多态的应用场景(二):父类当作方法的返回值,具体返回的是子类
}
}
public class test {
public static void main(String[] args) {
girl g=new girl();
animal a=petStore.getAnimal("cat");
g.play(a);//输出cat
}
}
final关键字/修饰符
final修饰变量,修饰类,修饰方法
1.修饰变量的四种情况
package com.msb;
public class teatFinal {
public static void main(String[] args) {
//第1种情况:
//final修饰一个变量,变量的值不可以改变,这个变量也变成了一个字符常量,约定俗成的规定:名字大写
final int A=10;//final修饰基本数据类型
//A=20;报错:不可以修改值
//第2种情况
final Dog d=new Dog();//final修饰引用数据类型,那么地址值就不可以改变
//d=new Dog();报错:因为地址值不可以改变
//d对象的属性依然可以改变,只是栈里的地址值不能更改
d.age=10;
d.weight=15.6;
//第3种情况
final Dog d2=new Dog();
a(d2);//这里不会报错,因为d指向的地址值是可以改变的,只有d2不可改变
//第4种情况
b(d2);
}
public static void a(Dog d){
d=new Dog();
}
public static void b(final Dog d){
//d=new Dog();报错:因为final修饰d之后,d的地址值不可以更改,所以不能再创建新的对象
}
}
public class Dog {
int age;
double weight;
}
2.修饰方法,修饰类
在同一个源文件中,只能有一个类被public修饰,并且被public修饰的类名必须跟源文件一样
math类的说明
抽象类,抽象方法
package com.msb;
public abstract class chouxiang {
//4.如果一个类中有抽象方法,那么这个类也必须使用abstract修饰,变成一个抽象类
//5.一个抽象类中可以有0-n个抽象方法
public void eat(){//1.在一个类中,会有一类方法,子类对这个方法非常满意,无需重写,直接使用
System.out.println("喜欢吃饭");
}
//3.一个方法的方法体去掉,然后被abstract修饰,那么这个方法就变成了一个抽象方法
public abstract void say();//2.在一个类中,会有一类方法,子类对这个方法永远不满意,会对这个方法进行重写
public abstract void sleep();
}
//6.抽象类可以被其他类继承
//7.一个类继承一个抽象类,那么这个类也可以变成抽象类
//8.一般子类不会加abstract修饰,一般会让子类重写父类中的抽象方法
//9.子类继承抽象类,就必须重写全部的抽象方法
//10.如果子类没有重写父类全部的抽象方法,那么子类也可以变成一个抽象类,一般让子类重写全部的抽象方法
class Student extends chouxiang{
@Override
public void say() {
}
@Override
public void sleep() {
}
}
class Demo{
public static void main(String[] args) {
//11.创建抽象类的对象-----》抽象类不可以创建对象
//chouxiang c=new chouxiang();报错
//12.创建子类对象
Student s =new Student();
s.say();
s.sleep();
//13.多态的写法,父类引用指向子类对象
chouxiang c=new Student();
c.say();
c.sleep();
}
}
面试题
接口
package com.msb;
/*1.类是类,接口是接口,他们是同一层次的概念
2.接口中没有构造器
3.接口如何声明:interface
4.在JDK1.8之前,接口中只有两部分内容:
(1)常量:固定修饰符:public static final
(2)抽象方法:固定修饰符:public abstract
注意:修饰符可以省略不写,IDEA会自动补全,初学者建议写上,防止遗忘*/
import com.msb.jicheng.Person;
public interface TeatInterface {
//常量
public static final int NUM=19;
//抽象方法
public abstract void a();
public abstract void b(int num);
public abstract int c(String name);
}
/*
5.类和接口的关系:实现关系,类实现接口
6.一旦实现一个接口,那么实现类要重写接口中的全部抽象方法
7.如果没有重写全部抽象方法,那么这个类可以变成一个抽象类
8.java只有单继承,Java还有多实现;一个类继承其他类,只能直接继承一个父类,但是实现类实现接口的话,可以实现多个接口
9.写法:先继承再实现*/
interface testInterface01{
void d();
void e();
}
class sky extends Person implements TeatInterface,testInterface01{
@Override
public void a() {
}
@Override
public void b(int num) {
}
@Override
public int c(String name) {
return 0;
}
@Override
public void d() {
}
@Override
public void e() {
}
}
class Test01{
public static void main(String[] args) {
//10.接口不能创建对象:
//TeatInterface t=new TeatInterface();
TeatInterface t=new sky();//接口指向实现类----》多态;也可以返回实现类---》多态
//11.接口中常量如何访问
System.out.println(TeatInterface.NUM);//(1)
System.out.println(sky.NUM);//(2)
sky s=new sky();//(3)
System.out.println(s.NUM);
TeatInterface t1=new sky();//(4)
System.out.println(t1.NUM);
}
}
JDK1.8之后的接口
包名和类名不能一样,包名一般小写,类名一般每个单词首字母大写,驼峰是前面小写后面大写
package com.msb.baoming;
public interface Interface {
//常量
public static final int NUM=10;
//抽象方法
public abstract void a();
//被public default 修饰的非抽象方法
public default void b(){//注意:1.default修饰符必须要加上,否则会出错
System.out.println("被public default 修饰的非抽象方法");
}
}
class Test00 implements Interface{
public void c(){//用一下接口中的b非抽象方法
b();//可以
//super.b();不可以
Interface.super.b();//可以
}
@Override
public void a() {
System.out.println("重写的 接口:Interface a方法");
}
@Override
public void b() {
System.out.println("实现类中要是想重写接口中的非抽象方法,那么default修饰符必须不能加,否则出错");
}
}
package com.msb.baoming;
public interface TestInterface2 {
//常量
public static final int NUM=20;
//抽象方法
public void a();
//非抽象方法
public default void b(){
System.out.println("被public default 修饰的非抽象方法");
}
//静态方法
public static void c(){
System.out.println("静态方法");
}
}
class Demo implements TestInterface2{
@Override
public void a() {
System.out.println("重写的 接口:Interface a方法");
}
public static void c(){
System.out.println("Demo 中的静态方法");
}
}
class Adomo{
public static void main(String[] args) {
Demo d=new Demo();
d.c();//执行的是Demo中的静态方法
//静态方法不能重写,只有非静态方法才可以重写
Demo.c();
TestInterface2.c();
}
}
内部类
package neibulei;
/*1.类的组成:属性,方法,构造器,代码块(普通块,静态块,构造块,同步块)
* 2.内部类:成员内部类和局部内部类(位置:方法内,块内,构造器内)
* 3.一个类的内部的类叫内部类
* 4.成员内部类:里面属性,方法,构造器等,修饰符可以是:private, default,protected,public,final,abstract
* 一般没有内部类再套内部类*/
public class TestOuter {
//成员内部类
public class De{
int age=20;
String name;
public void method(){//5.内部类可以访问外部类的内容
//System.out.println(age);
//a();
int age=30;
//8.内部类和外部类属性重名时,如何进行调用
System.out.println(age);//30
System.out.println(this.age);//20
System.out.println(TestOuter.this.age);//10
}
}
//静态成员内部类
static class Ef{
//6.静态内部类中只能访问外部类中被static修饰的内容
public void method(){
//System.out.println(age);报错
//a();报错
}
}
//属性:
int age=10;
public void a(){
System.out.println("这是a方法");
{
System.out.println("这是普通块");
class Bc{//块内的局部内部类
}
}
class Ab{//方法内的局部内部类
}
//7.外部类想要访问内部类的东西,需要创建内部类的对象,然后调用
De d=new De();
System.out.println(d.name);
d.method();
}
//构造块
{
System.out.println("这是构造块");
}
//静态块
static {
System.out.println("这是静态块");
}
//构造器
public TestOuter(){
class Cd{//构造器内的局部内部类
}
}
public TestOuter(int age){
}
}
class Demo{
public static void main(String[] args) {
//创建外部类的对象
TestOuter to=new TestOuter();
to.a();
//创建内部类的对象
//静态的成员内部类创建对象
TestOuter.Ef ef=new TestOuter.Ef();
//非静态的成员内部类创建对象
//TestOuter.De de=new TestOuter.De();报错;必须通过外部类才能创建
TestOuter t=new TestOuter();
TestOuter.De de=t.new De();
}
}
局部内部类(朗木达表达式?后面再说)
package neibulei;
public class Nei {
//1.在局部内部类中访问到的变量必须是被final修饰的
public void method(){
int num=10;
class A{
public void a(){
System.out.println(num);
}
}
}
//2.如果类B在整个项目中只使用一次,那么就没有必要单独创建一个B类,使用内部类就可以了
public Comparable method2(){
class B implements Comparable{
@Override
public int compareTo(Object o) {
return 100;
}
}
return new B();//接口当作返回值,那么返回的必须是实现类的具体的对象,一个小的多态的应用
}
public Comparable method3(){
//3.匿名内部类
return new Comparable() {
@Override
public int compareTo(Object o) {
return 0;
}
};
}
public void method4(){
Comparable com= new Comparable() {
@Override
public int compareTo(Object o) {
return 0;
}
};
System.out.println(com.compareTo("abc"));
}
}