1.类、对象、引用
1.1类
1.1.1类的介绍
1.类是具有相同属性和行为的对象的集合
2.类定义了该类型对象的数据结构,成为成员变量,同时还定义了一些可以被调用的功能,称为方法
3.类是用于构建对象的模板,对象的实质就是内存中的一块存储区域,其数据结构由定义它的类来决定
1.1.2类的定义
class 类名{
int x,y; //成员变量
public void 方法名(参数){ 方法要做的事情 }
}
package oopDay1;
//自定义一个用于描述点的类:Point
public class Point {
//类的属性
int x; //横坐标
int y; //纵坐标
//类的行为(方法)
// 定义一个公开的无参无返回值的方法move
public void move(){
y++;//纵坐标加1
}
public void move(int y){
//给成员变量y赋值
this.y=y; //this.y是类的属性的y
}
}
// new Piont() 然后设置x,y的值
// Piont p ,p是一个Point类型的变量,然后把x,y的值传进变量中
1.1.3成员变量
1.对象创建之后,其成员变量按照默认的方式初始化,对象成员具有初始化
成员变量的类型 | 默认初始值 |
byte、short、int、long | 0 |
boolean | false |
char | 空白字符 |
引用类型 | null |
1.2对象
1.2.1对象的介绍
1.当定义一个类之后,可以通过new 来创建该类的对象
2.对象创建的过程一般称为类的实例化
1.2.2语法规则
语法:类名 对象名= new 类名();
1.2.3成员变量和成员方法的调用
成员变量调用: 对象名.成员变量
成员方法调用:对象名.方法名()
package oopDay1;
public class TestPoint {
public static void main(String[] args) {
//1.创建对象
Point p = new Point();
//没有传数据都有它自己类型的默认值
System.out.println("("+p.x+','+p.y+")");//(0,0)
//2.修改对象的数据
p.x=5;
p.y=6;
System.out.println("("+p.x+','+p.y+")"); //(5,6)
//调用方法
p.move(); //y轴向上移动1
System.out.println("("+p.x+','+p.y+")");//(5,7)
//调用move方法,让y移动到指定位置
p.move(10);
}
}
1.3引用
1.除基本8种基本数据类型外都是引用类型
2.引用类型的变量中存储的是某个对象在内存中的地址信息
3.引用类型变量声明语法:类名引用类型变量名;
4.如果要输出一个对象中的信息的话,可以通过Arrays.toString()或者在该对象的类中重写toString方法
package oopDay1;
public class TestStudent {
public static void main(String[] args) {
Student stu = new Student();
System.out.println(stu);
//stu保存的是Student对象的内存地址 包名.类名@16进制整数 oopDay1.Student@1540e19d
//调用学生的方法
stu.score = 88;
stu.setName("小红");
stu.show();
System.out.println(stu.level());
}
}
2.JVM内存结构
2.1方法区
方法区用于存放类的信息,Java程序运行的时候,首先通过类加载入类文件的字节码文件,经过解析后将其装入方法区,类的各种信息都在方法区保存
2.2栈内存区
栈用于存放程序运行过程中的局部变量
引用类型的变量p存储在栈内存中
2.3堆内存区
堆内存区是jvm在其内存空间开辟的一个存储空间,用于存储使用new关键字创建的对象
3.方法的重载
3.1定义
方法的重载:方法名相同,参数不同(参数个数、参数数据类型);在一个类中可以存在多个方法名相同的方法,但是它们的参数列表必须不同;在调用方法时,会根据你传入的参数列表匹配对应的方法
package oopDay1;
//重载:
//方法同名不同参数(方法名相同,参数类型或个数必须不同)
public class Shape {
//计算圆的面积
public double area(int r) {
double a = Math.PI * Math.pow(r, 2);
return a;
}
//计算三角形的面积
public double area(double bottom, double h) {
double a = bottom * h/2;
return a;
}
}
3.2 this
1.可以通过this关键字表示调用该方法的对象
2.也可以使用this区分成员变量和参数
3.一个类可以创建多个对象(存储在堆中),但是方法只有一份(存储在方法区中)
4.构造函数
4.1定义构造方法
1.构造方法的名称和类名必须相同
2.构造方法没有返回值,但是不能用void修饰
4.2构造方法的重载
1.一个类可以定义多个构造方法,这些构造方法的参数列表不同
2.在创建对象时可以通过传入的参数列表找到对应的构造方法
package oopDay1;
public class Person {
String name;
String sex;
int age;
double money;
//无参构造函数
public Person(){
}
//2个参数的构造函数
public Person(String name, String sex) {
this.name = name;
this.sex = sex;
}
//自我介绍 无参数
public void intro() {
System.out.println("我是" + name + ",是一个" + sex + ",我今年"
+ age + "岁,我的存款:" + money);
}
//早餐吃什么 有一个参数,方法调用时必须要传一个参数
public void eat(String food) {
System.out.println("我正在吃:" + food);
}
}
5.继承
5.1继承的使用
1.extends关键字可以实现类的继承 子类 extends 父类;
2.子类可以继承父类的成员变量和方法,也可以定义自己的成员变量和方法;
3.一个类只能继承一父类,但是一个父类可以有多个子类,父类也可以再继承一个它的父类;
package oopDay2;
import java.util.Date;
//动物类 父类 公共属性:脚的数量 颜色 生日 性别 公共方法:叫 跑 吃
//鸡类: 属性:脚的数量 颜色 生日 性别 飞
//狗类: 属性:脚的数量 颜色 生日 性别 看门
public class Animal {
String color;
Date birth;
String sex;
int count;//脚的数量
public void intro(Animal animal) {
System.out.println("我是"+color+"的"+sex+"我有:"+count+"条腿,我的生日是"+birth);
}
public void sing(String sing){
System.out.println("叫"+sing);
}
public void eat(String food){
System.out.println("吃"+food);
}
public void run(){
System.out.println("到处跑");
}
}
class Chicken extends Animal{
public void fly(){
System.out.println("飞....");
}
}
class Dog extends Animal{
public Dog() {
}
public Dog(String color, Date birth, String sex, int count) {
}
public void seeDoor(){
System.out.println("看门");
}
}
5.2向上造型
1.语法: 父类类名 对象名 =new 子类类名();
2.在使用向上造型后,子类就只能使用父类中的方法,不能使用自己的方法
5.3向下造型:
1.将父类对象类型转为子类对象类型
2.语法:跟强制类型转换差不多
父类名 父类对象名 =new 父类类名();
子类名 子类对象名=(子类名) 父类对象名;
5.4 instanceof关键字
1.可以指向父类的对象也可以指向它的子类型的对象;
2.可以通过instanceof判断引用指向的对象的实际类型
package oopDay2;
import java.util.Date;
public class TestAnimal {
public static void main(String[] args) {
Chicken c = new Chicken();
c.color = "黄色";
c.sex = "母鸡";
c.birth = new Date();
c.count = 2;
c.fly();
c.eat("米");
c.run();
//向上造型:子类对象,赋值给父类的引用
Animal dog = new Dog("黑色", new Date(), "公狗", 4);
//dog.seeDoor(); //编译错误,dog引用的是Animal类型,Animal没有seeDoor方法
//如果要使用dog中的方法,需要 Dog dog = new Dog(),不能使用向上造型
dog.eat("骨头");
dog.run();
dog.sing("汪汪");
//创建Animal
Animal a1 = new Animal();
Animal a2 = new Chicken();
Dog a3 = new Dog();
//强制类型转换(父》子(向下转型)) a3是动物,本质上是狗,a3不能转为鸡这个类型
//如果不进行类型转换,就无法使用子类中独有方法和属性
if (a3 instanceof Dog) { //instanceof:用于判断 a3引用的对应的对象是否为Dog类型
//a3是Dog,把a3转换为Dog,然后赋值给Dog类型的引用
Dog dog1 = (Dog) a3;
}
if (a2 instanceof Chicken){
Chicken chicken=(Chicken) a2;
chicken.fly();
}
}
}
5.5继承中的构造方法
1.子类的构造方法中必须通过super调用父类的构造方法
2.子类的构造函数如果没有使用super调用父类的构造方法,Java编译器会自动加入对父类无参构造函数的调用(父类中要有无参构造方法)
package oopDay2;
public class Shape {
int x, y;
//构造函数
public Shape() {
System.out.println("shape的无参构造函数被调用");
}
public Shape(int x, int y) {
this.x = x;
this.y = y;
System.out.println("shape的有两个参数的构造函数被调用");
}
//成员函数
public double area() {
System.out.println("shape的area函数被调用");
return 0;
}
}
6.方法重写 overwrite
1.子类重复类继承的方法,子类可以对其重写(方法名、参数列表、返回值必须相同)
2.子类重写父类方法后,子类对象优先调用子类自己的方法
3.子类重写父类的方法时,可以通过super调用父类的方法
class Rect extends Shape {
double w;
double h;
public Rect() {
//super(); 需要写在第一行,构造器函数内部,会调用父类型的构造器函数,如果没有写super();编译器会主动添加
System.out.println("rect的无参构造函数被调用");
}
public Rect(int x, int y) {
super(x, y);
System.out.println("rect的两个参数的构造函数被调用");
}
public Rect(int x, int y, double w, double h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
System.out.println("rect的两个参数的构造函数被调用");
}
//方法重写:在不同的类中,同名同参
public double area() {
System.out.println("Rect的area函数被调用");
return w * h;
}
}
7.关键字
7.1 package
1.定义类的时候需要指定类的名称,但是会出现命名冲突的问题
2.给类指定一个包名可以解决命名冲突问题
3.类的命名: 包名+类名
---包名可以有层次结构,一个类可以有多层包名
---公司包名命名:公司域名反写 + 项目名 + 项目模块名 + mvc模式分层
7.2 import
7.3 return:方法中的定义
package oopDay3;
public class MethDemo {
//计算矩形周长并返回
public double girth(double w,double h){
return 2*(w+h);
}
//计算矩形的周长,不返回
public void girth1(double w,double h){
System.out.println("周长:"+2 * (w + h));
}
public static void main(String[] args) {
MethDemo m = new MethDemo();
System.out.println("周长:"+m.girth(1, 2));
m.girth1(3,5);//MethDemo类不是static,要访问其中的方法不能通过类名访问
}
}
7.4. static
7.4.1修饰成员变量
7.4.2修饰成员方法
package oopDay3;
public class Cat {
String name;
int age;
static int number; //static修饰的成员变量和方法可以通过类名访问
public Cat(){
number++; //new 一个猫,number就加一
}
public Cat(String name, int age) {
this.name = name;
this.age = age;
number++;
}
public static void print(){
//静态方法:通过类名直接调用;方法的内部不能使用this;也不能使用没有static修饰的成员变量
//非静态的方法可以通过对象调用
//System.out.println("姓名:"+name+",年龄:"+age);
System.out.println("当前有"+number+"只猫");
}
public static void main(String[] args) {
Cat c1 = new Cat("小红", 3);
c1.print();//number是1
Cat.number=100;
c1.print(); //number是100
Cat c2 = new Cat("rose", 2);
c2.print();//number是101
}
}
7.5 final
7.5.1修饰类
7.5.2修饰方法
7.5.3修饰成员变量
package oopDay3;
//Final:修饰的类不能被继承;修饰方法不能被重写;修饰属性,赋值之后,值不可改变
public class FinalDemo {
public static void main(String[] args) {
Coo coo = new Coo();
coo.print();
int age=18;
if (age >= Coo.MAX_AGE || age < Coo.MIN_AGE) {
System.out.println("年龄错误");
}else {
System.out.println("年龄正确");
}
System.out.println(Math.PI);//Math类中的常量
}
}
final class Aoo{ //final修饰的类不能被继承
}
class Boo{
public final void print(){
//final修饰的方法不能被重写
System.out.println("我是Boo中的print方法");
}
}
class Coo extends Boo{
int count;
final int size=100; //final修饰的变量,定义的时候赋值,复制之后,值不可改变
/*public void print(){ //编译错误,父类中的方法是final修饰的,不能被重写
}*/
//定义常量 用static和final修饰 ,可以通过类名调用
static final double PI=3.14;
//定义常量年龄,最大120,最小0
static final int MAX_AGE=120;
static final int MIN_AGE=0;
}
8.访问控制符
修饰符 | 本类 | 同一个包中的类 | 子类 | 其他类 |
public | 可以访问 | 可以访问 | 可以访问 | 可以访问 |
protected | 可以访问 | 可以访问 | 可以访问 | 不能访问 |
默认 | 可以访问 | 可以访问 | 不能访问 | 不能访问 |
private | 可以访问 | 不能访问 | 不能访问 | 不能访问 |
package oopDay2;
public class Cat {
String name; //没有public ,private , protected 的修饰, 所以就是默认的访问权限。
String sex;
//访问权限 public>protected>默认>private
public void catchMouse(){
System.out.println(name+"捉老鼠");
}
protected void eat(String food){
System.out.println(name+"吃:"+food);
}
private void sing(){
System.out.println("喵喵喵");
}
void play(){
System.out.println(name+"陪你玩");
}
}
9.对象数组
9.1介绍
9.1二维数组
package oopDay3;
import java.util.Arrays;
//二维数组
public class Array2Demo {
public static void main(String[] args) {
//基本数据类型的二维数组
int[][] arr=new int[5][]; //定义二维数组的时候,需要设置第一一维的长度
arr[0]=new int[5];
//数组的第一个元素,是一个长度为5的整形数组
arr[1]=new int[5];
arr[2]=new int[4];
arr[3]=new int[4];
arr[4]=new int[4];
//第二维的数组长度由一维的元素来确定
//遍历二维数组 循环的嵌套
//把一维的元素输出在一行显示
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {//arr[i]一维的元素
System.out.print(arr[i][j]+"\t");//arr[i][j]第二维数组中的元数
}
System.out.println();
}
System.out.println("=======================");
//定义一个长度是5的数组,数组的元素还是一个长度为5的数组
int[][] list=new int[5][5];
//遍历数组
for (int i = 0; i < list.length; i++) {
System.out.println(Arrays.toString(list[i]));
}
System.out.println("===========================");
//二维数组初始化
String[][] strs={{"A","B","C","D"},{"E","F","G","H"},{"H","I","J","K"}};
for (int i = 0; i < strs.length; i++) {
System.out.println(Arrays.toString(strs[i]));
}
//二维数组的赋值
Piont[][] ps=new Piont[3][3];
for (int i = 0; i < ps.length; i++) {
for (int j = 0; j < ps[i].length; j++) {
ps[i][j]= new Piont(i,j);
}
}
for (int i = 0; i < ps.length; i++) {
System.out.println(Arrays.toString(ps[i]));
}
}
}
10.抽象类
package oopDay3;
//abstract: 抽象 ,用于修饰类,表示这个类是一个抽象类
public abstract class Shape {
int x;
int y;
/* public double area(){//实现了的方法,并不呢体现出面积的计算公式,因为这个类不太方便计算面积
return 0;
}*/
public abstract double area();
//这是一个抽象方法,需定义在抽象类里面,只是定义了方法,并没有实现方法,相当于定义了一个规范,所有Shape类型的子类,都必须实现area方法
}
class Circle extends Shape {//继承了抽象类,需要重写抽象类中的方法
int r; //半径
@Override
public double area() {
return Math.PI * r * r;
}
}
class Rect extends Shape {
double w;
double h;
@Override
public double area() {
return w*h;
}
}
/*编译错误,非抽象类中不能出现抽象方法
抽象类中可以有抽象方法,也可以没有抽象方法
如果父类有抽象方法,子类要么重写抽象方法,要么把子类定义为抽象类
class Other{
public abstract double area();
}*/
11.接口
11.1接口的使用
1.接口可以看成是特殊的抽象类
2.接口中只能定义常量和抽象方法
3.一个类可以同时实现多个接口,接口之间用逗号分隔开,这个类需要实现所有接口中的抽象方法
4.一个接口可以通过extends继承另一个接口,子接口继承了父接口中的定义的所有方法
package oopDay4;
//interface 接口:只能写常量的定义,抽象方法的定义
//可以通过类实现接口,然后在类中重写这些接口中定义的方法
public interface Animal {
//定义常量
static final String OLEDER = "女娲";
//定义抽象方法 ,接口中的方法默认是 public abstract,可以省略
public void eat();
public void sleep();
public void sing();
}
//implements 实现 类需要实现接口中的所有抽象方法
//Cat实现了Animal接口,所以Cat是Animal
class Cat implements Animal {
String pinzgong;
String name;
public void catchMouse(){
System.out.println("抓老鼠");
}
@Override
public void eat() {
System.out.println("吃");
}
@Override
public void sleep() {
System.out.println("睡");
}
@Override
public void sing() {
System.out.println("叫");
}
}
12.内部类
12.1内部类
1.内部类:一个类定义在另一个类的内部,其所在的类成为外部类,其他类无法访问他
2.内部类一般只服务于外部类,内部类可以直接使用外部类的成员及方法
3.内部类不能独立于外部类存在,一般设置内部类为private
package oopDay4;
//内部类:类的内部包含一个其他类,这个被包含的类叫做内部类
//内部类对象的创建,需要先创建外部类对象,然后借助外部类对象创建内部类对象
//语法规则: 外部类的对象.new 内部类() 创建对象
public class Outer {
private String name;
private int x;
private int y;
public void out(){
System.out.println("外部类的out方法");
}
//内部类
class Inner{
String name;
String hobby;
//定义一个方法,用于输出外部类成员变量的值
public void print(){
//内部类和外部类的name重名,优先使用离自己近的
//可以通过外部类的类名.this来访问外部类的成员变量
System.out.println(Outer.this.name+":"+x+":"+y);
System.out.println("内部类的成员变量"+name +hobby);
//调用外部类的成员方法
out();
}
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.x=10;
outer.y=10;
outer.out();//调用自己类中的方法
//Inner inner = new Inner(); //编译错误,Inner是Outer中定义的内部类
//语法规定需要 外部类的对象.new 内部类() 创建对象
Inner inner = outer.new Inner();
inner.print(); //调用内部类的方法
System.out.println("======================");
//链式操作
Inner inner1 = new Outer().new Inner();
inner1.print();
}
}
12.2静态内部类
静态内部类:使用static修饰的成员内部类,在外部类加载时存在
package oopDay4;
import javax.lang.model.element.VariableElement;
public class Outer3 {
//静态内部类
static class Inner{
public void fun(){
System.out.println("静态内部类");
}
}
public static void main(String[] args) {
//完整写法
Inner inner = new Inner();
inner.fun();
//可以直接通过new创建对象的时候访问
new Inner().fun();
}
}
12.3匿名内部类
匿名内部类:在一段程序中需要创建一个类对象,创建之后就没价值了,这个类可以不用命名
Timer timer = new Timer();
//匿名内部类的使用
timer.schedule(new TimerTask() {//TimerTask是一个抽象类
@Override
public void run() {
System.out.println("起床了");
}
}, 1000, 1000);
12.4局部内部类
局部内部类:定义在方法中的类
package oopDay4;
//局部内部类:定义在方法内的一个类
public class TestInner2 {
public void fun(){
class Inner{
public void fun(){
System.out.println("局部内部类");
}
}
Inner inner = new Inner();//局部内部类只能用在其所在的成员方法中
inner.fun();//调用的是内部类的fun方法
}
public static void main(String[] args) {
TestInner2 ti2 = new TestInner2();
ti2.fun();
}
}
13.值传递&引用传递
1.如果一个方法参数为引用类型,直接修改参数的属性值会对其造成影响
2.如果一个方法参数为引用类型,在该方法中又创建了新对象,不会对实际参数造成影响
3.如果一个方法参数为原始类型,该方法不会对实际参数造成影响
4.每一个字符串都是一个新的对象
package oopDay5;
public class Arguments {
public static void main(String[] args) {
Point point = new Point();
point.x = 10;
point.y = 10;
point.print();//(10,10)
// testPoint(point);//实际参数 是引用类型
// point.print();//(11,10)
testPoint1(point);
point.print();//(10,10)
String str = "你好";//创建对象,赋值给引用
testStr(str);
System.out.println("最后的str:" + str);
/*输出
* str:你好
str:中国
最后的str:你好
* */
int i = 1;
int j = 1;
testInt(i, j);//(10,10)
System.out.println("最后的:(" + i + "," + j + ")");//(1,1)
}
public static void testPoint(Point p) {
p.right();
}
public static void testPoint1(Point p) {
p = new Point();//给引用赋值一个新的对象,不会对实际参数造成影响
p.right();
}
public static void testStr(String str) {
System.out.println("str:" + str);
str = "中国";//每个字符串都是一个新对象
System.out.println("str:" + str);
}
public static void testInt(int i, int j) {
i = 10 * i;
j = j * 10;
System.out.println("(" + i + "," + j + ")");
}
}
14.==和equals的区别
1.==:基本数据类型,判断数据值是否相等;引用类型,判断引用指向的地址是否相等
2.equals:默认是比较对象的地址是否相等;重写之后,判断对象的所有值相等
package oopDay5;
// == :用于判断基本数据类型的数据值是否相等,用于判断引用类型的地址是否相等
// equals:用于判断对象的内存是否相等
public class EqualsDemo {
public static void main(String[] args) {
int a = 10;
int b = 10;
System.out.println(a == b);//true
Point p1 = new Point(10, 10);
Point p2 = new Point(10, 10);
System.out.println(p1 == p2); //false 判断引用类型地址是否相等
Student s1 = new Student("1001", "小红", "java2202");
Student s2 = new Student("1001", "小红", "java2202");
System.out.println(s1 == s2);//false
Student s3 = s1;
System.out.println(s3 == s1);//true 引用的是同一个对象
System.out.println(p1.equals(p2));//false 在Point类中equals没有重写,判断的是两个对象的引用地址是否相等
System.out.println(s1.equals(s2));//true 在Student类中重写了equals方法,判断的是值是否相等
}
}
15.面向对象3大特性
15.1封装
1.通过private对属性修饰,提供公开的get和set方法
2.自动生成get、set方法:右键——generate或alt+insert——getter and setter,选择要生成的属性
15.2继承
1.Java中是单继承,一个子类只有一个父类,一个父类可以有多个子类
15.3多态
1.对象是多种状态的
2.父类的引用指向子类的对象: Father s=new Son();
package oopDay5;
public class Printer {
public void print(){
System.out.println("打印机可以打印");
}
public static void main(String[] args) {
//多态
Student stu1 = new Student();
stu1.name="tom";
Student stu2 = new Student();
stu2.name="jack";
Printer p1 = new Printer3D();
Printer p2 = new PrinterBlack();
Printer p3 = new PrinterColor();
p1.print();
p2.print();
p3.print();
}
}
class Printer3D extends Printer{
@Override
public void print() {
System.out.println("3D打印机");
}
}
class PrinterBlack extends Printer{
@Override
public void print() {
System.out.println("黑白打印机");
}
}
class PrinterColor extends Printer{
@Override
public void print() {
System.out.println("彩色打印机");
}
}
16.静态代码块
16.1静态代码块
1.语法: static{ 代码 }
2.静态代码块在类加载时执行,只执行一次
16.2非静态代码块
1.语法: { 代码 }
2.在创建对象时执行,每创建一个对象就要执行一次
package oopDay5;
public class CodeBlockDemo {
private int x;
static double pi;
static {//类加载完成(只加载一次),执行静态代码块
System.out.println("静态代码块");
pi=3.14;
}
{//非静态代码块,创建对象的时候,执行非静态代码块
System.out.println("非静态代码块");
x=10;
}
public CodeBlockDemo() {
System.out.println("对象创建成功");
}
public static void main(String[] args) {
CodeBlockDemo cbd1 = new CodeBlockDemo();
CodeBlockDemo cbd2 = new CodeBlockDemo();
}
//成员方法
public void add(){
x++;
}
public void add(int k){
x+=k;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CodeBlockDemo)) return false;
CodeBlockDemo that = (CodeBlockDemo) o;
return x == that.x;
}
}
17.总结
17.1感悟
我是之前学过Java面向对象的知识的,当时对子类父类的使用有一些模糊,还有接口、抽象类里面可以定义些什么也不是很清楚,经过这段时间的学习,我感觉自己对这些之前不太清楚的知识点有了更新的认识,差不多已经是全部掌握;还有就是static修饰的属性和方法的知识是掌握了的,但是在做测试题的时候没怎么注意就会出错。
17.2测试错题
1.给出下面代码, 那个语句是正确的?( )
public class Person{
int arr[] = new int[10];
public static void main(String a[]) {
System.out.println(arr[1]);
}
}
[A]编译时将产生错误; arr[]是非静态的,不能在静态方法里面使用
[B] 编译时正确,运行时将产生错误;
[C] 输出零; [D] 输出空;
17.3面试题
1.面向对象的特点?
---封装:使用private对属性修饰,提供公开的get、set方法
---继承:子类继承父类,子类可以使用父类中的属性和方法
---多态:对象是多种状态的
2.你怎么理解面向对象?
面向对象:侧重于创建解决事情的实体,就是把现实中的事物都抽象为“对象”。每个对象是唯一的,且都可以拥有它的属性与行为。我们就可以通过调用这些对象的方法、属性去解决问题。
3.面向对象和面向过程的区别?
---面向过程:侧重于解决问题的步骤,就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
---面向对象:侧重于创建解决事情的实体,就是把现实中的事物都抽象为“对象”。每个对象是唯一的,且都可以拥有它的属性与行为。我们就可以通过调用这些对象的方法、属性去解决问题。
4.接口和抽象类的区别是什么 ?
---接口:使用interface修饰,只能定义常量和抽象方法,实现接口需要重写接口中所有的方法
---抽象类:使用abstract修饰,可以有非抽象方法,继承抽象类可以不用重写抽象方法(自己也为抽象类)
5.成员变量与局部变量的区别有那些 ?
---成员变量:属于类,可以被访问控制符、static等修饰;存储在堆内存中;没有初始化有默认值
局部变量:是在方法中定义的变量或方法的参数,不可以被访问控制符、static等修饰;存储在栈内存中;没有初始化没有值
6.创建一个对象用什么运算符?对象实体与对象引用有何不同?
---使用new创建对象
---对象实体:存在堆内存中,一个对象可以有多个对象引用指向它
---对象引用:存在栈内存中,一个对象引用可以指向0个或1个对象
7.什么是方法的返回值?返回值在类的方法里的作用是什么?
---返回值:是某个方法体中的代码执行后产生的结果,通过return 返回
---作用:接收结果,使得它可以用于其它操作
8.一个类的构造方法的作用是什么?若一个类没有声明构造方法,该程序能正确执行吗 ?为什么?
---构造方法作用:在创建对象时进行初始化
---没有构造方法程序也能正常运行,默认有一个无参构造方法
9.构造方法有哪些特性 ?
---构造方法名和类名相同
---构造方法没有返回值,但是不能用void修饰
---一个类可以有多个构造函数,但是它们的参数列表不同
10.对象的相等与指向他们的引用相等,两者有什么不同?
---对象相等:对象存储的内容相等,表示是同一对象
---引用相等:两个引用指向的地址相等
11.在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
---因为子类继承父类之后,获取到了父类的属性和方法,而这些在使用之前必须先初始化,所以必须先调用父类的构造函数进行内容的初始化.
12.构造块、静态块、构造方法中的方法执行顺序是怎样的?
---先执行静态代码块,再执行构造代码块,最后执行构造方法
13.普通类和抽象类有哪些区别?
---抽象类:被abstract修饰,不能实例化,子类继承抽象类,需要对其所有抽象方法进行重写,如果子类也是抽象类,可以不用重写,抽象类中的普通方法和属性需要子类的对象去调用
14.抽象类能使用 final 修饰吗?
---不能,抽象类必须被继承,用final修饰后就不可被继承