黑马程序员部分
project(工程) > (src) > package(包) > class(类) > object(对象)> 成员(变量,函数和内部类)
一个类中可以有成员变量、方法,还可以有内部类。内部类实际上是它所在类的成员。内部类最重要的特点就是能够访问外部类的所有成员
面向对象编程三大特性
封装,继承,多态
Java中的变量:
1.成员变量(实例变量,属性)
2.本地变量(局部变量)
3.类变量(静态属性)
byte 字节 就是2个16进制数 00到FF 8位
1024 byte = 1k b
Java基本类型占用的字节数:
1字节: byte , boolean
2字节: char,short
4字节: int , float
8字节: long , double
附录:
编码:
数字都是一个1字节
GBK: 中文2字节
UTF-8: 中文通常3字节,在拓展B区之后的是4字节
int默认10进制,数字前面加0b表示2进制,0x表示16进制
普通变量
对象变量(管理者)
new VendingMachine();
VendingMachine v = new VendingMachine();
对象变量是对象的管理者
运算符.
类的首字母大写
tip(%占位符,%d整数%f小数)
编译单元(.java文件):一个编译单元最多只能有一个class是public
包(管理机制)
类变量
public class Display{
private static int step = 1;
}
- d1.step = d2.step = Display.step
- 可通过对象访问类变量,但是类变量不属于对象
- 类函数(static函数)
属于类的函数,可以访问其他类函数
public class Display{
public static viod main = {};
}
static成员的初始化和对象的创建没关系
泛型容器类
对象数组
对象不存在则为null
//对字符串数组a而言
String[] a = new String[10];
for (String k : a){
k = "good";
}
集合容器
class Value{
public String toString(){return ""+i;}
}
Hash表
private HashMap<Interger,String> coinnames = new HashMap<Interger,String>();
coinnames.put(key,value)
coinnames.keySet() //得到key表
coinnames.keySet().size()
coinnames.get(index)
基于已有的设计创造新的设计,就是面向对象程序设计的继承
代码复制是代码质量不良的表现,不好维护
public:所有人都能访问
protected:包内和包外的子类可以访问
缺省:包内可以访问
private:只有类自己可以访问
构造子类对象时,先进构造函数头,再进父类的构造函数初始化,再进入定义初始化,再去做构造函数的剩下部分。
可以理解为:
父类的定义初始化和构造初始化做完后,再做子类的定义和构造初始化
没有super()会默认去找父类中没有参数的构造器,如果有super(),就根据super()中的参数来寻找父类的构造函数。
在构造一个子类的对象时,父类的构造方法也是会被调用的,而且父类的构造方法在子类的构造方法之前被调用。在程序运行过程中,子类对象的一部分空间存放的是父类对象。因为子类从父类得到继承,在子类对象初始化过程中可能会使用到父类的成员。所以父类的空间正是要先被初始化的,然后子类的空间才得到初始化。在这个过程中,如果父类的构造方法需要参数,如何传递参数就很重要了。
子类如果有函数和父类同名,使用super.func()来调用父类的那个函数(父类这个函数是可访问时)
父类item和子类DVD
//Item.java
package database;
public class Item {
private String title;
private int playingTime;
private boolean gotIt;
private String comment;
public Item(String title, int playingTime, boolean gotIt, String comment) {
this.title = title;
this.playingTime = playingTime;
this.gotIt = gotIt;
this.comment = comment;
}
// public void setTitle(String title) {
// this.title = title;
// }
public void print() {
System.out.print(title+" ");
}
public static void main(String[] args){
}
}
//DVD.java
package database;
public class DVD extends Item {
private String director;
public DVD(String title,String director,int playingTime, boolean gotIt, String comment) {
super(title,playingTime,gotIt,comment);
this.director = director;
}
public void print() {
System.out.print("DVD: ");
super.print();
System.out.print(director);
}
public static void main(String[] args){
DVD dvd = new DVD("lovelyy","wjj",120,false,"...");
dvd.print();
}
}
- 用括号围起来的类型放在值的前面称为造型
- 对象本身没有发生任何变化,所以不是“类型转换(int i = (int)10.2)”,要区分(虽然英语的单词都是cast)!
- 运行时有机制来检查这样的转化是否合理(ClassCastException)
- 向下造型例子
对于DVD变量d,Item类对象v
d = (DVD) item;
需要v被指向一个DVD这个子类对象。如果没有指向,那在编译时时没问题的,但是运行时会产生错误
多态
Object类
java是单根结构,所有的类都是Object类的子类,Object类是root类
@override
public boolean equals(Object obj){
CD cc = (CD)obj;
return artist.equals(cc.artist);
}
例子:dome的新媒体类型
String是一个immutable(不可修改)的对象,当需要很多复杂的字符串操作来产生一个结果字符串时,为防止系统开销过大,可使用StringBuffer对象,这是一个可以不断修改的对象。最后用toString()产生一个String对象就可以
//Game(Main).java
package castle;
import java.util.HashMap;
import java.util.Scanner;
public class Game {
private Room currentRoom;
private HashMap<String, Handler> handlers = new HashMap<String, Handler>();
public Game()
{
handlers.put("go", new HandlerGo(this));
handlers.put("help",new HandlerHelp(this));
handlers.put("bye", new HandlerBye(this));
createRooms();
}
private void createRooms()
{
Room outside, lobby, pub, study, bedroom;
// 制造房间
outside = new Room("城堡外");
lobby = new Room("大堂");
pub = new Room("小酒吧");
study = new Room("书房");
bedroom = new Room("卧室");
// 初始化房间的出口
outside.setExit("east", lobby);
outside.setExit("south",study);
outside.setExit("west",pub);
lobby.setExit("west", outside);
pub.setExit("east", outside);
study.setExit("north",outside);
study.setExit("east",bedroom);
bedroom.setExit("west", study);
lobby.setExit("up", pub);
pub.setExit("down", lobby);
currentRoom = outside; // 从城堡门外开始
}
private void printWelcome() {
System.out.println();
System.out.println("欢迎来到城堡!");
System.out.println("这是一个超级无聊的游戏。");
System.out.println("如果需要帮助,请输入 'help' 。");
System.out.println();
showPrompt();
}
// 以下为用户命令
public void goRoom(String direction)
{
Room nextRoom = currentRoom.getExit(direction);
if (nextRoom == null) {
System.out.println("那里没有门!");
}
else {
currentRoom = nextRoom;
showPrompt();
}
}
public void showPrompt() {
System.out.println("现在你在" + currentRoom);
System.out.print("出口有:");
System.out.print(currentRoom.getExitDesc());
System.out.println();
}
public void play() {
Scanner in = new Scanner(System.in);
while ( true ) {
String line = in.nextLine();
String[] words = line.split(" ");
Handler handler = handlers.get(words[0]);
String value ="";
if (words.length > 1)
value = words[1];
if (handler != null) {
handler.doCmd(value);
if (handler.isBye())
break;
}
// if ( words[0].equals("help") ) {
// game.printHelp();
// } else if (words[0].equals("go") ) {
// game.goRoom(words[1]);
// } else if ( words[0].equals("bye") ) {
// break;
// }
}
in.close();
}
public static void main(String[] args) {
Game game = new Game();
game.printWelcome();
game.play();
System.out.println("感谢您的光临。再见!");
}
}
//Room.java
package castle;
import java.util.HashMap;
public class Room {
private String description;
private HashMap<String,Room> exits = new HashMap <String, Room>();
public Room(String description)
{
this.description = description;
}
public String getExitDesc() {
StringBuffer sb = new StringBuffer();
for (String dir : exits.keySet()) {
sb.append(dir);
sb.append(" ");
}
return sb.toString();
}
public Room getExit(String direction) {
return exits.get(direction);
}
public void setExit(String dir, Room room) {
exits.put(dir,room);
}
@Override
public String toString()
{
return description;
}
}
//Handler.java
package castle;
public class Handler {
protected Game game;
public Handler(Game game) {
this.game = game;
}
public void doCmd(String word){}
public boolean isBye() {
return false;
}
}
//HandlerBye
package castle;
public class HandlerBye extends Handler {
public HandlerBye(Game game) {
super(game);
}
@Override
public boolean isBye() {
return true;
}
}
//HandlerHelp
package castle;
public class HandlerHelp extends Handler {
public HandlerHelp(Game game) {
super(game);
}
@Override
public void doCmd(String word) {
System.out.println("迷路了吗?你可以做的命令有:go bye help");
System.out.println("如:\tgo east");
}
}
//HandlerGo
package castle;
public class HandlerGo extends Handler {
public HandlerGo(Game game) {
super(game);
}
@Override
public void doCmd(String word) {
game.goRoom(word);
}
}
public abstract class Shape {
public abstract void draw(Graphics g);
}
接口所有的方法都是没有方法体的,而且都是public abstract,即使你没有这样声明。而接口中的所有成员变量都是public static final的变量,并且必须有定义初始化,因为所有变量都必须在编译的时候有确定值。
接口和类的地位是一样的。因此我们可以看到其定义方式跟类也是基本上一样的。当然,其中的所有方法都没有方法体。而当类从接口得到继承的时候,Java用另外一个动词:实现(implements)。当然,实现接口的类必须覆盖接口中所有的方法,否则这个类就成为一个抽象类。
Java不允许多继承,但是允许一个类实现多个接口,也允许一个接口从多个接口得到继承,但是不允许接口从类继承。
//Cell.java
package cell;
import java.awt.Graphics;
public interface Cell{
void draw(Graphics g,int x,int y,int size);
}
//Fox.java
package animal;
import java.awt.Color;
public class Fox extends Animal implements Cell {
public Fox() {
super(20,4);
}
@Override
public void draw(Graphics g, int x, int y, int size) {
int alpha = (int)((1-getAgePercent())*255);
g.setColor(new Color(0, 0, 0, alpha));//(int)((20-getAge())/20.0*255)));
g.fillRect(x, y, size, size);
}
@Override
public Animal breed() {
Animal ret = null;
if ( isBreedable() && Math.random() < 0.05 ) {
ret = new Fox();
}
return ret;
}
@Override
public String toString() {
return "Fox:"+super.toString();
}
@Override
public Animal feed(ArrayList<Animal> neighbour) {
Animal ret = null;
if ( Math.random()< 0.2 ) {
ret = neighbour.get((int)(Math.random()*neighbour.size()));
longerLife(2);
}
return ret;
}
}
- (Swing框架)Jframe的布局管理器(Layout Manager)是BorderLayout
- North,South,West,East,Center
内部类就是指一个类定义在另一个类的内部,从而成为外部类的一个成员。因此一个类中可以有成员变量、方法,还可以有内部类。实际上Java的内部类可以被称为成员类,内部类实际上是它所在类的成员。所以内部类也就具有和成员变量、成员方法相同的性质。比如,成员方法可以访问私有变量,那么成员类也可以访问私有变量了。也就是说,成员类中的成员方法都可以访问成员类所在类的私有变量。内部类最重要的特点就是能够访问外部类的所有成员
JTable可以以表格的形式显示和编辑数据。JTable类的对象并不存储数据,它只是数据的表现。数据和表现是分离的
try{
//可能产生异常的代码
} catch(Exception e1){
//处理e1异常的代码
} catch(Exception e2){
//处理e2异常的代码
}
出现异常后一直往外层找try,简单说就是异常会由内向外抛出,知道被捕捉到,或者在最外层也没有捕捉到,就会输出异常,终止程序。
catch(ArrayIndexOutOfBoundsException e){
System.out.println(e.getMessage());
System.out.printlin(e);
e.printStackTrace();//打印出调用堆栈追踪
}
//catch(Exception e)会捕捉所有的异常
catch(Exception e){
System.err.println("An exception was throw");
throw e;//捕捉到处理了之后想再度抛出
try{
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}catch(fileOPenFailed){
doSomethin;
}catch(sizeDeterminationFailed){
doSomething;
}......
异常机制最大的好处就是清晰的分开了正常的业务逻辑代码和遇到情况时的处理代码
异常发生时必须停下了让其他地方的代码来处理执行
public class TooBig extends Throwable{}
public class TooSmall extends Throwable{}
public class DivZero extends TooSmall{}
public class Test{
void f() throws TooBig,TooSmall,DivZero{
throws new DivZero();
}
public static void main(String[] args){
try{
f();
}catch(TooSmall e){
//doSomething
}
}
}
byte[] buf = new byte[10];
for (int i=0;i<buf.length;i++){
buf[i]=(byte)i;
}
try{
int i = Oxcafebabe;//int默认10进制,0b表示2进制,0x表示16进制
//输出流(内存的二进制数据的写入dat文件)
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream("a.dat")));
out.writeInt(i)
out.close;
//输入流(dat文件二进制数据读入内存)
DataInputStream in = new DataInputStream(
new BufferedInputStream(
new FileInputStream("a.dat")));
int j = in.readInt();
System.out.println(j)
try{
//文本数据写入文本文件
PrintWriter out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter( //构建stream和writer的桥梁
new FileOutputStream("a.txt")));
int i = 123456;
out.printInt(i);
out.close();
//文本文件写入内存
BufferedReader in = new BufferedReader(
new InputStreamReader( //构建stream和Reader的桥梁
new FileOutputStream("src/hello/Main.java")));
String line;
while ((line=in.readLine())!=null){
System.out.println(line);
}
//文本文件写入内存
BufferedReader in = new BufferedReader(
new InputStreamReader( //由这个来管理
new FileOutputStream("utf-8.txt"),"utf-8"));
String line;
while ((line=in.readLine())!=null){
System.out.println(line);
格式化输入输出
printWriter(输出)
Scanner(输入)
流的应用
package stream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class Main {
public static void main(String[] args) {
try {
Socket socket = new Socket(InetAddress.getByName("localhost"),12345);
PrintWriter out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream())));
out.println("Hello");
out.flush();
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
String line;
line = in.readLine();
System.out.println(line);
out.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package stream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Student implements Serializable{
private String name;
private int age;
private int grade;
public Student(String name, int age, int grade) {
this.name = name;
this.age = age;
this.grade = grade;
}
public String toString() {
return name +" " + age +" " + grade;
}
}
public class ObjectStream {
public static void main(String[] args) {
Student s1 = new Student("wjj",23,100);
System.out.println(s1);
try {
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("obj.dat"));
out.writeObject(s1);
out.close();
ObjectInputStream in = new ObjectInputStream(
new FileInputStream("obj.dat"));
Student s2 = (Student)in.readObject();
System.out.println(s2);
in.close();
System.out.println(s1==s2);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
学完了,感谢翁恺老师的Java课程
参考链接 https://www.cnblogs.com/ysocean/p/8194428.html
执行:静态代码块→构造方法块→构造函数→普通函数
总结: 子类必须调用父类构造方法,不写则赠送super(),,写了则调用指定的super调用,super只能有一个且必须为第一个语句。
接口的定义类可以添加自己多的成员方法
是多个类的规范标准,只要符合,就可以大家通用
public interface 接口名称{
//接口内容
//可以包含1常量,2抽象方法,(java8之后)3默认方法,4静态方法(java9后增加了5私有方法)
}
// 换成关键字interface之后,编译生成的字节码文件依然是.java→.class
//接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
//这两个关键字修饰符可以选择性的忽略
public interface InterfaceAbs{
public abstract voidmethodAbs();
}
如果实现类没有覆盖重写接口中所有的抽象方法,那么这个类自己就必须是抽象类
1.接口不能直接使用,必须有一个实现类来实现该接口
格式:public class 实现类名称 implements接口名称{}
2. 接口的实现类必须覆盖重写(实现)接口中的所有抽象方法。
实现:去掉abstract关键字,加上方法体大括号
3. 创建实现类的对象,进行使用
public可以省略,default不能省略
public可以省略
接口的私有方法定义和使用
我们需要抽取一个共有方法,不应该让实现类使用,应该是私有化的。
常量(接口中的成员变量)
接口中也可以定义“成员变量”,但是必须使用public static final修饰,从效果上看,这其实就是接口的常量
final关键字一旦赋值,不可改变
注意事项与总结
类与类之间的关系
extends和implements都适用多态
父类引用指向子类对象称为多态
多态访问成员变量的两种方式
Fu obj() = new Zi();
System.out,println(obj.num);//用的Fu的成员变量
理解成员变量没有覆盖重写这一说!!!
多态访问成员方法的两种方式
总结:
成员变量:编译成功否看左,运行还看左(等号左右)
成员方法:编译成功否看左,运行看右(等号左右)
多态的作用
无论右边new的时候换成哪个子类对象,等号左边调用方法都不会变化。
向上转型
作用见上
其实就是多态写法,父类引用指向子类对象
父类名称 对象名 = new 子类对象();
Animal animal = new Cat();
向上转型一定是安全的,因为范围由小变大。
弊端:一旦向上转型为父类,那么就无法调用子类特有的方法
解决方案,使用对象的向下转型
必须保证对象本来创建的时候就是猫,向下转型才能成为猫
如果对象创建的时候本来不是猫,现在非要向下转型成猫,就会报错
用instanceof关键字判断对象类型
对象 instanceof 类名称
返回布尔值,可用if做判断
使用向下转型一定要用instanceof来进行类型判断再做相应操作
案例
有了USB接口这个统一标准,笔记本电脑只要把参数写成usb就行了。外接设备只要能实现USB功能就可以和笔记本电脑联系起来(没有直接联系,通过usb接口间接联系)。
不可变,最终的
对类、方法来说,abstract和final关键字不能同时使用,因为矛盾
一个类包含另一个类
//成员内部类直接使用方式
Body.Heart heart = new Body().new Heart();
-
//使用匿名内部类
Myinterface obj = new MyInterface(){
@override
public void method(){
System.out.println("a");
}
};
类和接口都可以作为成员变量类型
接口也可以作为方法的参数和返回值
只要涉及到类型,任何数据类型都能使用。