精华内容
下载资源
问答
  • 第二种: String str = Class.forName(String).newInstance() <br />两种方法创建的对象实体没有任何区别,如果硬说有区别的话,就是第一种直接调用了本类的构造函数,如果本类有多个构造函数重载...

    以String类为例
    第一种:
    String str = new String();
    第二种:
    String str = Class.forName(String).newInstance()

    两种方法创建的对象实体没有任何区别,如果硬说有区别的话,那就是第一种直接调用了本类的构造函数,如果本类有多个构造函数重载的话,可以添加参数。而第二种是调用这个类的默认构造函数,即不带任何参数的。
    第一种方法是最常用,最普遍的用法。
    第二种方法叫做工厂模式,是一种较安全的方法。

    展开全文
  • 你自己脑海中想出几种解法? 举例几种解法 解法一 n阶行列式的值,等于任意一行(列)的元素与其代数余子式的乘积的和 解法二: 一行白鹭上青天 解法三 多种数学解法,读到过高中的应该都看的懂吧! 遇到问题没人...

    今天看了一个题目,这道题目很多解法。那究竟有哪些呢?又哪一种最简答了!你自己脑海中想出几种解法?

    举例几种解法

    解法一
    在这里插入图片描述
    n阶行列式的值,等于任意一行(列)的元素与其代数余子式的乘积的和

    解法二:
    在这里插入图片描述
    一行白鹭上青天

    解法三

    多种数学解法,读到过高中的应该都看的懂吧!
    在这里插入图片描述

    遇到问题没人解答?小编创建了一个Python学习交流QQ群:895817687 寻找有志同道合的小伙伴,
    互帮互助,群里还有不错的视频学习教程和PDF电子书!
    

    解法四:

    只用加减的方法:

    1+2+3+4+5-6-7+8-9

    1+2+3+4-5+6+7-8-9

    1+2+3-4-5-6-7+8+9

    1+2-3+4-5-6+7-8+9

    1+2-3-4+5+6-7-8+9

    1+2-3-4+5-6+7+8-9

    1-2+3+4-5+6-7-8+9

    1-2+3+4-5-6+7+8-9

    1-2+3-4+5+6-7+8-9

    1-2-3+4+5+6+7-8-9

    1-2-3-4+5-6-7+8+9

    1-2-3-4-5+6+7-8+9

    我第一眼看到这题目想到的答案:
    在这里插入图片描述
    我感觉不能在简单明了了!

    身为程序员的你,你会用怎样的方式解答呢?

    展开全文
  • 众所周知,数据存储在每个应用中都会用到,所用到的技术应该怎么选呢,这里Android给开发者提供了几种方法去保存常用应用数据,至于你想选择一种方式,取决于你的特定需求;例如这个数据是本应用私有的...

    前言

    众所周知,数据存储在每个应用中都会用到,那所用到的技术应该怎么选呢,这里Android给开发者提供了几种方法去保存常用应用数据,至于你想选择哪一种方式,取决于你的特定需求;例如这个数据是本应用私有的还是跟其它应用共享以及数据存储所需的内存空间等

    • Shared Preferences:这种方式通常用来保存私有原始数据,以键值对形式存储;这也就意味着这些数据只能由本应用访问
    • Internal Storage:这种方式是将私有数据保存在内部存储(设备内存)中,实际上是使用文件流进行读写
    • External Storage:这种方式是将公共数据存储在共享外部存储上;也就是将数据存储在SD卡上,存储在这上面说明数据是开放的,其它应用可以直接访问;这跟上面一种都是平常所说的文件存储
    • SQLite Databases:这种方式是将结构化数据存储在私有数据库中;这也就是常说的数据库存储,使用SQLite保存数据,这些数据是私有的
    • Network Connection:这种方式是将数据存储在Web服务器上,也就是通常所说的网络存储

    笔者上一篇文章讲述了第二种和第三种方式的使用封装,这篇文章来掰掰第四种方式,也就是数据库存储

    数据库存储

    本文所含代码随时更新,可从这里下载最新代码
    传送门Mango

    做Android开发的绝大多数应该都用过Sqlite了,开发者可以使用它来保存应用私有数据,这里简单介绍下Sqlite

    • SQLite是一个进程内库:它实现了一个独立的,无服务器,零配置的事务SQL数据库引擎,且支持SQL语句
    • SQLite是一个嵌入式SQL数据库引擎:与大多数其他SQL数据库不同,SQLite没有单独的服务器进程; SQLite直接读写普通磁盘文件;数据库文件格式是跨平台的,可以在32位和64位系统之间自由复制数据库
    • SQLite是一个紧凑的库:启用所有功能后,库大小可能小于600KiB,具体取决于目标平台和编译器优化设置;通常情况下给与的内存越多,运行越快;即使在低内存环境中,性能通常也非常好,SQLite可以比文件系统I / O更快
    • Sqlite最重要的一点是开源的

    现在一些主流的移动设备,比如Android,iPhone,pad等都在使用Sqlite存储数据,这也就意味着我们必须要掌握SQLite的开发

    其实SQLite还有一个最大的特点是你可以把各种类型的数据保存到任何字段中,而不用关心字段声明的数据类型是什么;一般其它数据库采用的是静态数据类型,即你定义的字段类型是什么,那存入的数据就得是相应的数据类型;但是SQLite采用的是动态数据类型,会根据存入值自动判断;比如可以在Integer类型的字段中存放字符串,或者在布尔型字段中存放浮点数,或者在字符型字段中存放日期型值;但有一种情况例外:定义为INTEGER PRIMARY KEY的字段只能存储64位整数, 当向这种字段保存除整数以外的数据时,将会产生错误

    数据库创建

    内置存储数据库

    创建新SQLite数据库的推荐方法是创建SQLiteOpenHelper的子类并覆盖onCreate()方法,在该方法中可以执行SQLite命令以在数据库中创建表

    /**
     * @Description TODO(数据库及表创建)
     * @author cxy
     * @Date 2018/11/5 11:07
     */
    public class SQLiteDBHelper extends SQLiteOpenHelper{
    
        //类还没有实例化,只能是static修饰才能用来做参数
        private static final String DATABASE_NAME = "mango";
        private static final String TABLE_USER = "user";
        private static final int DATABASE_VERSION = 1;
    
        /**
         * 重载构造方法
         * @param context
         */
        public SQLiteDBHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
    
        /**
         * 构造方法
         * @param context 上下文
         * @param name 数据库名
         * @param factory 游标工厂,默认为null,即使用默认工厂
         * @param version 数据库版本号
         */
        public SQLiteDBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
        }
    
        /**
         * 数据库第一次创建时被调用
         * 用来创建表
         * 或者一些数据初始化操作
         * @param db
         */
        @Override
        public void onCreate(SQLiteDatabase db) {
            String dataBaseSql = "create table if not exists " + TABLE_USER+ "(uid integer primary key autoincrement,name varchar(20),sex varchar,role varchar(10))";
            db.execSQL(dataBaseSql);
        }
    
        /**
         * 升级软件时更新数据库表结构
         * 通过比对版本号
         * 一般做删除数据表,并建立新的数据表操作
         * @param db
         * @param oldVersion 上一次版本号
         * @param newVersion 最新版本号
         */
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    
        }
    
        /**
         * 打开一个只读数据库
         * 如果数据库不存在,Android系统会自动生成一个数据库,接着调用onCreate()方法
         * @return 获取一个用于操作数据库的SQLiteDatabase实例
         */
        @Override
        public SQLiteDatabase getReadableDatabase() {
            return super.getReadableDatabase();
        }
    
        /**
         * 创建或打开一个读写数据库
         * 如果数据库不存在,Android系统会自动生成一个数据库,接着调用onCreate()方法
         * @return 获取一个用于操作数据库的SQLiteDatabase实例
         */
        @Override
        public SQLiteDatabase getWritableDatabase() {
            return super.getWritableDatabase();
        }
    }
    
    • SQLiteOpenHelper是Android提供的一个供开发者使用SQLiteDatabase的辅助类,用来管理数据库及表的创建和版管理
    • 重写构造方法,传递必要的参数,在这里数据库还没有创建,只是构建一个用于创建,打开或者管理数据库的辅助类实例
    • 重写onCreate方法,当数据库第一次创建时,这个方法被调用(不需要用户手动调用),用来创建表和初始化数据
    • 重写onUpgrade方法,当数据库版本变化时被调用;比如淘宝APP要升级,同时一些表结构变了,像表User多了一个字段,但是用户手机上还是原来的数据库,表User没有新的字段,那这时候APP要想正常工作就需要修改版本号,在这个方法中去对表User做一些修改
    • getReadableDatabase和getWritableDatabase方法都是用来获取一个用于操作数据库的SQLiteDatabase实例,但getWritableDatabase() 方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,倘若使用getWritableDatabase()打开数据库就会出错;getReadableDatabase()方法先以只读方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库
    • 数据库真正的创建是在调用getReadableDatabase和getWritableDatabase两个方法的时候,创建完后才会回调onCreate方法创建表;并且这两个方法在数据库upgrade时可能会花费较长时间,不要在主线程调用

    注意:在这里有一个版本号的规范问题,在API24中,在打开或者创建数据库时,如果之前的数据库版本号与最新的版本号不一致,同时之前的版本号是0,那只会回调onCreate方法(这也是首次使用默认历史版本号为0);如果经过了N个版本更新后,新的版本号比历史版本号大,那就回调onUpgrade方法;如果新的版本号小于历史版本号,那就回调onDowngrade方法,这个方法有一个默认实现是抛出异常;所以编写版本号的时候一定要注意

    public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            throw new SQLiteException("Can't downgrade database from version " +
                    oldVersion + " to " + newVersion);
    }
    

    外置存储数据库

    上面方法创建数据库,db文件是存放在内置存储中,路径在data/data/包名/databases 目录下,如果某些情况下出现问题需要获取数据库文件进行分析,那显然操作内置存储是很不方便的,并且内置存储内存空间有限,对数据存储限制比较大;这时候我们就可以在外置存储中创建数据库文件,通常做法是提前使用工具创建好数据库文件,并创建好相关表,然后放到工程assets目录或者raw目录下,在程序运行时将db文件拷贝到SD卡,再通过SQLiteOpenHelper访问这个数据库

    这里推荐大家一款SQLite可视化工具SQLiteManager,可用它来创建一个db文件,并且创建你需要的表
    我这里创建了一个mango.db数据库文件,并且创建了一个user表,字段与上面一样

    那接下来怎么让程序使用到这个SD卡上的db文件呢?如果无从下手,那就看看默认的getReadableDatabase和getWritableDatabase方法是怎么创建数据库的

    不管是getReadableDatabase还是getWritableDatabase方法,都没做啥处理,将逻辑全部转到了getDatabaseLocked方法,那就来看看这个方法(API24)

    private SQLiteDatabase getDatabaseLocked(boolean writable) {
    
            ......
    
            SQLiteDatabase db = mDatabase;
            try {
                mIsInitializing = true;
    
                if (db != null) {
                    if (writable && db.isReadOnly()) {
                        db.reopenReadWrite();
                    }
                } else if (mName == null) {
                	//如果传入的数据库名是null,那就使用默认路径创建数据库
                    db = SQLiteDatabase.create(null);
                } else {
                    try {
                        if (DEBUG_STRICT_READONLY && !writable) {
                            final String path = mContext.getDatabasePath(mName).getPath();
                            db = SQLiteDatabase.openDatabase(path, mFactory,
                                    SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                        } else {
                        	//如果名称不为null,那就构建data/data/包名/databases/mName路径
                            db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
                                    Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
                                    mFactory, mErrorHandler);
                        }
                    } catch (SQLiteException ex) {
                        if (writable) {
                            throw ex;
                        }
                        final String path = mContext.getDatabasePath(mName).getPath();
                        db = SQLiteDatabase.openDatabase(path, mFactory,
                                SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                    }
                }
    
                onConfigure(db);
    						
    			//这里根据版本号判断是否需要数据库升级还是降级
                final int version = db.getVersion();
                if (version != mNewVersion) {
                    if (db.isReadOnly()) {
                        throw new SQLiteException("Can't upgrade read-only database from version " +
                                db.getVersion() + " to " + mNewVersion + ": " + mName);
                    }
    
                    db.beginTransaction();
                    try {
                        if (version == 0) {
                            onCreate(db);
                        } else {
                            if (version > mNewVersion) {
                                onDowngrade(db, version, mNewVersion);
                            } else {
                                onUpgrade(db, version, mNewVersion);
                            }
                        }
                        db.setVersion(mNewVersion);
                        db.setTransactionSuccessful();
                    } finally {
                        db.endTransaction();
                    }
                }
    
                onOpen(db);
    
                if (db.isReadOnly()) {
                    Log.w(TAG, "Opened " + mName + " in read-only mode");
                }
    
                mDatabase = db;
                return db;
            } finally {
                mIsInitializing = false;
                if (db != null && db != mDatabase) {
                    db.close();
                }
            }
        }
    

    这里可以看到一句很重要的话就是当mName不为null的时候,调用

    mContext.openOrCreateDatabase
    

    这里的mContext是我们在构造SQLiteOpenHelper传进来的,它是Activity的上下文,指的是ContextWrapper,具体实现是ContextImpl(具体可以参考博主的从Activity加载源码深入理解ActivityThrad的工作逻辑),进到这个类看看

    @Override
        public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
            return openOrCreateDatabase(name, mode, factory, null);
        }
    
        @Override
        public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
                DatabaseErrorHandler errorHandler) {
            checkMode(mode);
            File f = getDatabasePath(name);//构建数据库文件
            int flags = SQLiteDatabase.CREATE_IF_NECESSARY;
            if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) {
                flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;
            }
            if ((mode & MODE_NO_LOCALIZED_COLLATORS) != 0) {
                flags |= SQLiteDatabase.NO_LOCALIZED_COLLATORS;
            }
            SQLiteDatabase db = SQLiteDatabase.openDatabase(f.getPath(), factory, flags, errorHandler);
            setFilePermissionsFromMode(f.getPath(), mode, 0);
            return db;
        }
    

    这里表明默认情况下数据库文件是通过ContextWrapper的实现类创建的,并且是存放在内置存储中,路径data/data/包名/databases/mName

    那解决方法也就出来了,我们只要定义一个类,继承ContextWrapper,重写openOrCreateDatabase方法,获取SD卡上的db文件路径,然后再调用SQLiteDatabase类的openOrCreateDatabase方法即可获取SQLiteDatabase实例,然后返回;
    这样操作以后,getDatabaseLocked方法中的mContext.openOrCreateDatabase具体实现就是我们编写的这个方法了

    /**
     * @Description TODO(加载SD卡上的db)
     * @author cxy
     * @Date 2018/11/5 17:04
     */
    public class DataBaseContext extends ContextWrapper{
    
        public DataBaseContext(Context base) {
            super(base);
        }
    
        /**
         * 重写这个方法,加载SD卡的数据库
         * @param name
         * @param mode
         * @param factory
         * @param errorHandler
         * @return
         */
        @Override
        public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
            String dbPath = FileStorageTools.getInstance(this).makeFilePath("/Android/data/"+getPackageName()+"/database/"+SQLiteDBHelper.DATABASE_NAME+".db");
            File file = new File(dbPath);
            if (!file.exists()) throw new NullPointerException("DB File is not exists");
            SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(dbPath,null);
            return database;
        }
    }
    

    其中的FileStorageTools类可查看博主上一遍文章

    接下来只需要在实例化SQLiteDBHelper的时候传递这个自定义的Context对象就可以了

    DataBaseContext baseContext = new DataBaseContext(context);
    SQLiteDBHelper mHelper = new SQLiteDBHelper(baseContext);
    

    通过SQLiteDatabase 对象的getPath()方法,你就知道你使用的数据库存放在哪了

    编写DAO

    我们先写个父类

    
    /**
     * @Description TODO()
     * @author cxy
     * @Date 2018/11/5 18:12
     */
    public class BaseDao {
    
        protected WeakReference<DataBaseContext> mContext;
        protected SQLiteDBHelper mHelper;
    
        public BaseDao(Context context) {
            mContext = new WeakReference<>(new DataBaseContext(context));
            mHelper = new SQLiteDBHelper(baseContext);
        }
    }
    

    我们前面创建了一个user表,然后再编写对应的dao

    /**
     * @Description TODO(提供对user的操作)
     * @author cxy
     * @Date 2018/11/5 14:50
     */
    public class UserDao extends BaseDao{
    
        private String TAG = UserDao.class.getSimpleName();
    
        public UserDao(Context context) {
            super(context);
        }
    
        public void addUser(User user){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            String sql = "insert into " + SQLiteDBHelper.TABLE_USER + "(uid,name,sex,role) values(?,?,?,?)";
            database.execSQL(sql,new String[]{user.getUid(),user.getName(),user.getSex(),user.getRole()});
            database.close();
        }
    
        /**
         *
         * @param user
         * @return 插入的新纪录的行号,即是第多少行
         */
        public long addUserValues(User user){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put("uid",user.getUid());
            values.put("name",user.getName());
            values.put("sex",user.getSex());
            values.put("role",user.getRole());
            long rowNum = database.insert(SQLiteDBHelper.TABLE_USER,null,values);
            database.close();
            return rowNum;
        }
    
        public void updateUser(String uid,String name,String sex){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            String sql = "update " + SQLiteDBHelper.TABLE_USER + " set name = ? where uid = ? and sex = ?";
            database.execSQL(sql,new String[]{name,uid,sex});
            database.close();
        }
    
        public void updateMoreUser(String uid,String uid2,String uid3,String name){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            String sql = "update " + SQLiteDBHelper.TABLE_USER + " set name = ? where uid in (?,?,?)";
            database.execSQL(sql,new String[]{name,uid,uid2,uid3});
            database.close();
        }
    
        /**
         *
         * @param sex
         * @param name
         * @return 受影响的行数总和
         */
        public int updateUserValues(String sex,String name){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put("name",name);
            int rowNum = database.update(SQLiteDBHelper.TABLE_USER,values,"sex = ?",new String[]{sex});
            database.close();
            return rowNum;
        }
    
        public void delUser(String uid){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            String sql = "delete from " + SQLiteDBHelper.TABLE_USER + " where uid = ?";
            database.execSQL(sql,new String[]{uid});
            database.close();
        }
    
        public void delAllUser(){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            String sql = "delete from " + SQLiteDBHelper.TABLE_USER ;
            database.execSQL(sql);
            database.close();
        }
    
        /**
         *
         * @param sex
         * @return  受影响的行数总和
         */
        public int delUserValues(String sex){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            int rowNum = database.delete(SQLiteDBHelper.TABLE_USER,"sex = ?",new String[]{sex});
            database.close();
            return rowNum;
        }
    
        /**
         *
         * @return 受影响的行数总和
         */
        public int delALLUserValues(){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            int rowNum = database.delete(SQLiteDBHelper.TABLE_USER,null,null);
            database.close();
            return rowNum;
        }
    
        public User getUser(String uid){
            User user = new User();
            SQLiteDatabase database = mHelper.getWritableDatabase();
            String sql = "select * from "+ SQLiteDBHelper.TABLE_USER + " where uid = ?";
            Cursor cursor = database.rawQuery(sql,new String[]{uid});
            while (cursor.moveToNext()) {
                user.setUid(cursor.getInt(cursor.getColumnIndex("uid"))+"");
                user.setName(cursor.getString(cursor.getColumnIndex("name")));
                user.setSex(cursor.getString(cursor.getColumnIndex("sex")));
                user.setRole(cursor.getString(cursor.getColumnIndex("role")));
            }
            cursor.close();
            database.close();
            return user;
        }
    
    
    }
    
    /**
     * @Description TODO()
     * @author cxy
     * @Date 2018/11/5 14:53
     */
    public class User {
    
        private String uid;
        private String name;
        private String sex;
        private String role;
    
        public String getUid() {
            return uid;
        }
    
        public void setUid(String uid) {
            this.uid = uid;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public String getRole() {
            return role;
        }
    
        public void setRole(String role) {
            this.role = role;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "uid='" + uid + '\'' +
                    ", name='" + name + '\'' +
                    ", sex='" + sex + '\'' +
                    ", role='" + role + '\'' +
                    '}';
        }
    }
    

    在应用启动的时候要记得将db文件拷贝到SD卡

    private void moveDBFile(){
            boolean isDbFileExist = true;
            File dbFile;
            String path = "/Android/data/"+getPackageName()+"/database/";
            File parent = new File(FileStorageTools.getInstance(this).makeFilePath(path));
            if (!parent.exists()) {
                parent.mkdirs();
                isDbFileExist = false;
                dbFile = FileStorageTools.getInstance(this).makeFile(parent, SQLiteDBHelper.DATABASE_NAME+".db");
            } else {
                dbFile = FileStorageTools.getInstance(this).makeFile(parent, SQLiteDBHelper.DATABASE_NAME+".db");
                if (!dbFile.exists()) {
                    isDbFileExist = false;
                }
            }
            if (!isDbFileExist) {
                FileStorageTools.getInstance(this).moveResourceFileToExternalStorage(dbFile,FileStorageTools.getInstance(this).getStreamFromRaw(R.raw.mango));
            }
        }
    

    我这里简单写了几个数据库操作的方法,数据库操作无外乎增删改查,这些操作SQLiteDatabase 都提供了api供我们使用,我们重点要掌握它的execSQL()和rawQuery()方法; execSQL()方法可以执行insert、delete、update和CREATE TABLE等有更改行为的SQL语句; rawQuery()方法用于执行select语句

    假如你不会编写Sql语句,不用担心,Android很贴心的, SQLiteDatabase专门提供了对应于添加、删除、更新、查询的操作方法: insert()、delete()、update()和query();你只需要传递相应的参数就能完成数据库操作,有没有很激动;对于熟悉SQL语法的程序员而言,直接使用execSQL()和rawQuery()方法执行SQL语句其实更方便

    执行SQL语句的方法有了,那就要学会编写相应的SQL语句了

    插入操作

    • 它的SQL语句格式:insert into 表名(字段列表) values(值列表)

    举例:

    insert into user(uid,name,sex,role) values("1","tom","1","2")
    

    这种写法就是一个字段对应一个值,但是实际上这种写法不利于开发效率,当字段多的时候,你需要对语句进行拼接,很容易出现错误,而且使得语句变得非常长,不利于维护;同时,这些值有可能是用户输入的,里面可能会包含特殊符号,比如单引号,&类似的符号,为了保证语句正确执行,你必须对每个字段进行转义,对每条语句都这样操作很麻烦

    针对这种问题,SQLiteDatabase类提供了一个重载后的execSQL(String sql, Object[] bindArgs)方法,使用这个方法可以解决前面提到的问题,因为这个方法支持使用占位符参数(?)

    我们就可以这样写了

    insert into user(uid,name,sex,role) values(?,?,?,?)
    SQLiteDatabase.execSQL(sql,new String[]{user.getUid(),user.getName(),user.getSex(),user.getRole()});
    
    • 另一种非SQL语句写法
    ContentValues values = new ContentValues();
    values.put("uid",user.getUid());
    values.put("name",user.getName());
    values.put("sex",user.getSex());
    values.put("role",user.getRole());
    database.insert(SQLiteDBHelper.TABLE_USER,null,values);
    

    insert方法需要三个参数

    • 第一个参数:要插入数据的表的名称
    • 第二个参数:指定空值字段的名称;当第三个参数为空或者里面没有内容的时候,我们insert是会失败的(底层数据库不允许插入一个空行),构建成的sql语句:insert into user() values(),显然这不满足标准SQL的语法;为了防止这种情况,我们要在这里指定一个列名,到时候如果发现第三个参数为null或者其元素个数为0,就会将你指定的这个列名的值设为null,然后再向数据库中插入,这时候构建成的语句:insert into user(name) values(NULL)
    • 第三个参数:一个ContentValues对象,类似一个map,通过键值对的形式存储值,key为列名,values为值

    第三个参数如果不为null且元素个数不为0,也就是通过putXXX方法存储了值,那第二个参数就可以为null

    更新操作

    • 它的SQL语句格式:update 表名 set 字段名=值 where 条件子句

    举例:

    update user set name = ? where uid = ?
    database.execSQL(sql,new String[]{name,uid});//执行
    

    这就是将指定uid的一行记录中的name字段更新成指定值

    这里条件表达式可以用and或者or来表示

    //这个表示两个条件必须都满足才更新行记录
    String sql = "update user  set name = ? where uid = ? and sex = ?";
    database.execSQL(sql,new String[]{name,uid,sex});
    //只要有一个条件满足就更新行记录
    String sql = "update user  set name = ? where uid = ? or sex = ?";
    database.execSQL(sql,new String[]{name,uid,sex});
    

    有时候条件表达式中一个字段有多个值范围的,比如你要更新uid等于1,2,3,4的多个行记录,这时候要用到 in

    String sql = "update user  set name = ? where uid in (?,?,?)";
    database.execSQL(sql,new String[]{name,uid,uid2,uid3});
    
    • 非SQL语句写法
    public int updateUserValues(String uid,String name){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put("name",name);
            int rowNum = database.update(SQLiteDBHelper.TABLE_USER,values,"sex = ?",new String[]{sex});
            database.close();
            return rowNum;
    }
    

    这里通过调用SQLiteDatabase 的update方法

    • 第一个参数是表名
    • 第二个参数是要修改的列名对应的值(也就是每行记录中字段对应的值)
    • 第三个参数就是判断条件(把SQL语句中的where后面的拿过来就可以了)
    • 第四个参数是条件对应的值

    删除操作

    • 它的SQL语句格式:delete from 表名 where 条件子句

    举例:

    String sql = "delete from user where uid = ?";
    database.execSQL(sql,new String[]{uid});
    

    条件表达式同更新操作中一样

    如果要删除所有数据,去掉条件表达式即可

    String sql = "delete from user  " ;
    database.execSQL(sql);
    
    • 非SQL语句写法
    public int delUserValues(String uid){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            int rowNum = database.delete(SQLiteDBHelper.TABLE_USER,"uid = ?",new String[]{uid});
            database.close();
            return rowNum;
    }
    

    delete方法参数与更新操作中一样

    如果要删除全部数据,第二个参数和第三个参数传入null

    public int delALLUser(){
            SQLiteDatabase database = mHelper.getWritableDatabase();
            int rowNum = database.delete(SQLiteDBHelper.TABLE_USER,null,null);
            database.close();
            return rowNum;
    }
    

    注意:update和delete方法的返回值表明影响的行数总和,insert方法返回值是新插入行的行ID,如果发生错误,则为-1

    查询操作

    毫无疑问,查询操作应该是用的最频繁的也是最复杂多变的一个操作了,SQLiteDatabase给我们提供了query和rawQuery两类查询方法,它们都会返回一个Cursor对象,Cursor是一个游标接口,代表数据集的游标,提供了遍历查询结果的方法,它的API如下

    Cursor API

    • int getCount() :获得查询后的数据总条数
    • boolean isFirst():光标是否指向第一个条目
    • boolean isLast():光标是否指向最后一个条目
    • boolean isBeforeFirst():光标是否指向第一行之前的位置
    • boolean isAfterLast():光标是否指向最后一行之后的位置
    • boolean isNull(int columnIndex):指定列数据是否为null
    • boolean move(int offset):将光标从当前位置向前或向后移动相对量。 正偏移向前移动,负偏移向后移动。 如果最终位置超出结果集的边界,则结果位置将固定为-1或count();返回值是是否移动成功
    • boolean moveToPosition(int position):将光标移动到绝对位置。 有效值范围是-1 <= position <= count;返回值是是否移动成功
    • boolean moveToFirst():将光标移动到第一行,返回值是是否移动成功
    • boolean moveToLast():将光标移动到最后一行,返回值是是否移动成功
    • boolean moveToNext():将光标移动到下一行,返回值是是否移动成功
    • boolean moveToPrevious():将光标移动到上一行,返回值是是否移动成功
    • int getColumnIndex(String columnName):返回给定列名称的从零开始的索引,如果该列不存在,则返回-1
    • int getInt(int columnIndex):返回当前行指定列的值
    • long getLong(int columnIndex):同上
    • float getFloat(int columnIndex):同上
    • String getString(int columnIndex):同上

    查询方法

    再看几个查询方法

    • public Cursor rawQuery(String sql, String[] selectionArgs)

    这第一个参数是执行查询的SQL语句,第二个是语句中对应占位符的值

    • public Cursor query(String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having, String orderBy)

      • table:表名
      • columns:需要返回的列,传入null将返回所有列(尽量不要传入null,将会从消耗多余的性能)
      • selection:查询条件子句,相当于select语句where关键字后面的部分,在条件子句允许使用占位符“?”
      • selectionArgs:对应于selection语句中占位符的值,值在数组中的位置与占位符在语句中的位置必须一致,否则就会有异常
      • groupBy:用于设定返回行的分组方式,传递null表示返回的行不会被分组;相当于select语句group by关键字后面的部分
      • having:决定哪一行被放到Cursor中的过滤器,相当于select语句having关键字后面的部分;传递null会导致所有的行都包含在内,前提是groupBy属性也设置为null
      • orderBy:用于设定行的排列方式(依据列值),相当于select语句order by关键字后面的部分;传递null表示使用默认的排序方式,可能是无序排列
    • public Cursor query(String table, String[] columns, String selection,String[] selectionArgs, String groupBy, String having,
      String orderBy, String limit)

      这里比上面方法多了一个参数limit,设置query语句返回行的数量,执行分页功能,相当于select语句limit关键字后面的部分;传递null表示没有设置limit语句;注意格式为String,传递的时候需要传递数字字符串,例如“10”

    • public Cursor query(boolean distinct, String table, String[] columns,String selection, String[] selectionArgs, String groupBy,
      String having, String orderBy, String limit)

      这个方法比上面的又多了一个参数distinct,是用来去重的,设置为true,每一行的数据必须唯一

    查询样例

    它的SQL语句格式:select column1, column2,…columnN from 表名 where 条件子句 group by 分组字句 having … order by 排序子句 (顺序一定不能错)

    举例:

    • where
    //查询user表所有记录
    select * from user 
    
    //查询uid=2的记录
    select * from user where uid = 2
    
    //查询uid大于2的记录
    select * from user where uid > 2
    
    //查询uid等于2或者3的记录
    select * from user where uid in (2,3)
    
    //查询uid既不是 2也不是 3的记录
    select * from user where uid not in (2,3)
    
    //查询uid在2和5之间的记录
    select * from user where uid between 2 and 5
    
    //查询uid等于2且sex=1的记录
    select * from user where uid =2 and sex = 1
    
    //查询uid等于2或者且sex=1的记录
    select * from user where uid =2 or sex = 1
    
    //查询name以jack开头的记录
    select * from user where name like 'jack%'
    
    //查询name以jack结尾的记录
    select * from user where name like '%jack'
    
    //查询name包含jack的记录
    select * from user where name like '%jack%'
    
    
    • limit
    //查询user表前10条记录
    select * from user limit 10
    
    //查询user表从第10条开始的后10条记录
    select * from user limit 10 offset 10
    
    
    • group by

    假如表里很多条记录,记录着每个人每个月的收入,这里就会存在多条记录是同一个人的
    然后我要查出来每个人总共收入是多少,这时候可以用到group by了,将同一个人的多条记录合并成一条记录,会让其中的收入字段值累加,从而的得到每个人的总收入,表里现有记录如下

    uid name income
    1 jack 1000
    2 jack 1000
    3 tom 500
    4 aliex 500
    5 tom 1000
    6 jack 2000
    select name,income from user group by name 
    

    执行这个语句后,查出来的记录如下

    name income
    jack 4000
    tom 1500
    aliex 500
    • order by
    select name,income from user group by name order by income asc
    

    这个语句执行的结果就是在上面的基础上将记录按照income字段升序排列,得到如下结果

    name income
    aliex 500
    tom 1500
    jack 4000

    还可以用 order by income desc,这个就是降序排列

    • having
      having 子句在由 group by 子句创建的分组上设置条件,在一个查询中,having 子句必须放在 group by 子句之后,必须放在 order by 子句之前

    比如现在有这样一个例子:
    有三个人,他们中了很多次奖,中奖记录存放在user表中,现在老板想看下每个人总共中了多少奖,也就是拿了多少钱,同时对中奖人的条件是中奖次数要大于1次,也就是说只中奖一次的人就不要给我看了

    先看看原始数据

    uid name income
    1 jack 1000
    2 jack 1000
    3 tom 500
    4 aliex 500
    5 tom 1000
    6 jack 2000

    执行下面这个语句

    select name,income from user group by name having count(name) > 1
    

    这里的count是计数功能,count(name) > 1表示每个分组中的分组标志name要出现一次以上,得到如下结果

    name income
    jack 4000
    tom 1500

    因为name=aliex的分组中name只出现了一次,所以被排除了

    事务(Transaction)

    事务是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行;使用事务的好处是可以保证数据的一致性和完整性(避免异常和错误等导致的数据信息异常) ;比如我要批量的插入一批数据,要么全插入成功,要么一条也别插入

    事务(Transaction)具有以下四个标准属性,通常根据首字母缩写为 ACID

    • 原子性(Atomicity):确保工作单位内的所有操作都成功完成,否则,事务会在出现故障时终止,之前的操作也会回滚到以前的状态
    • 一致性(Consistency):数据库从一个一致性状态变到另一个一致性状态(一系列操作后,所有的操作和更新全部提交成功,数据库只包含全部成功后的数据就是数据的一致性;相反,由于系统异常或数据库出现故障导致只有部分数据更新成功,这不是我们需要的最终数据,这就是数据的不一致)
    • 隔离性(Isolation):使事务操作相互独立和透明(事务内部操作的数据对其它事务是隔离的,在一个事务执行完之前不会被其他事务影响和操作)
    • 持久性(Durability):确保已提交事务的结果或效果在系统发生故障的情况下仍然存在

    事务的使用:

    主要四步:beginTransaction -> sql操作 -> setTransactionSuccessful -> endTransaction

    //往数据库批量插入记录
    public  boolean batchInsertBySql(List<String> list) {
            SQLiteDatabase db = null;
            try {
                db = sqlConnection.getWritableDatabase();
                
                db.beginTransaction();//开始事务
                for (String str : list) {
                    StringBuffer sql = new StringBuffer(200);
                    sql.append("insert into terminal_deviceinfo  values(")
                    .append(str)
                    .append(");");
                    db.execSQL(sql.toString());
                }
                db.setTransactionSuccessful();//设置事务的标志为成功,这样执行到endTransaction() 时提交当前事务,如果不调用此方法会回滚事务
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            } finally {
                try {
                    if (null != db) {
                        db.endTransaction();//由事务的标志决定是提交事务,还是回滚事务
                        db.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return true;
        }
    

    SQL注入

    SQL注入是比较常见的网络攻击方式,注入通常在请求用户输入时发生,比如需要用户输入姓名,但用户却输入了一个 SQL 语句,这个语句能做的事太多了,非常严重的是删除数据库了

    案列

    • 案例一

    比如用户登录,需要输入用户名,然后用户输入了

    tom'; delete from user;
    

    此时一个疏忽的程序猿去判断表里有没有这个人,通过如下语句

    select * from user where name='{$name}'
    

    那这个语句最后就是

    select * from user where name='tom'; delete from user
    

    像这种堆叠查询语句很明显会对数据库造成非常大的损失

    • 案例2

    在登录界面,需要用户输入用户名和密码,然后用户输入的用户名如下

    ‘or 1 = 1 --
    

    这时候又一个疏忽的程序猿这样去数据库判断用户存不存在

    String sql = "select * from user where name=' "+userName+" ' and password=' "+password+" ' "
    

    这个语句接上上面用户的输入内容

    select * from user where name= '‘ or 1 = 1 -- and password = ' '
    

    where后面接了两个条件,name= '‘ 或者 1 = 1,那这必然成立的,且后面接了 – 表示后面判断password 的语句就变成了注释,就没有作用了;那这样用户就随便登录了

    防止SQL注入

    编写SQL语句的时候切记不要直接使用字符串拼接的方式,使用参数化SQL,可以使用 ? 这个占位符填充参数值的位置;Google在Sqlite里弄了很多重载的函数,像上面提到的几种查询方法,就是参数化SQL的效果,参数化处理就是为了防止SQL注入

    对用户输入的内容进行字符串过滤,判断输入内容是否包含一些特殊符号和SQL关键字

    总的说来,防范一般的SQL注入只要在代码规范上下点功夫就可以了

    展开全文
  • 简单工厂模式是由一个工厂对象决定创建一种产品类的实例。 1.工厂模式的几种形态 工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以动态决定将一个类实例化,不必事先知道每次要实例化一个类。工厂...
  • java中的反射

    2019-05-23 19:15:00
     以前我们创建对象有几种方式?只有一种方式去new一个对象。有的时候在程序的开发阶段,你并不知道要创建哪 个类的对象,或者你不知道要调用类的哪个方法,或者访问类的哪个属性。在程序的运行阶段,你才知道要...

    一.什么是反射,反射有什么用

      以前我们创建对象有几种方式?只有一种方式去new一个对象。有的时候在程序的开发阶段,你并不知道要创建哪
    个类的对象,或者你不知道要调用类的哪个方法,或者访问类的哪个属性。在程序的运行阶段,你才知道要创建哪
    个类的对象。那怎么解决这种问题?
    研究一下spring的核心的源码的业务逻辑,分以下几个步骤
      1,读取applicationContext.xml,获取所有的bean标签的class属性
      2,获取bean标签的class属性之后,class属性的值在java程序中应该以什么数据类型来存储,用字符串类型来存储
      3,根据class属性的字符串描述符来创建一个这个描述符描述的对象。需求到这一步,就变成:
      根据一个字符串,来创建一个字符串描述的对象。
    使用反射必须先获取类的Class对象,每个类在java的虚拟机中,默认都会存在一个class的对象。如果要使用反
    射,必须先获取这个Class对象。
    二.class对象的使用
      1.Class对象获取的三种方式
    创建Person.java
    package com.aaa.spring.entity;
    /**
    * 人员类
    */
    public class Person {
    }
    /**
    * Class对象获取的三种方式
    */
    public class Test02 {
    public static void main(String[] args) throws Exception {
    //获取Person的Class对象
    //第一种方式,通过Class.forName()
    Class clazz1 = Class.forName("com.aaa.spring.entity.Person");
    System.out.println(clazz1);
    //第二种方式 访问类的class对象
    Class clazz2 = Person.class;
    System.out.println(clazz2);
    //第三种方式,通过对象的getClass方法
    Person person = new Person();
    Class clazz3 = person.getClass();
    System.out.println(clazz3);
    }
    }

      2.利用Class对象获取构造方法

    创建Person2.java

    package com.aaa.spring.entity;
    public class Person2 {
    //默认无参的构造
    public Person2(){}
    //公共的有一个参数的方法
    public Person2(String name){}
    //私有的有两个参数的方法
    private Person2(String name,int age){}
    }
    /**
    * 利用CLass对象获取构造方法
    */
    public class Test03 {
    public static void main(String[] args) throws Exception {
    //获取类的Class对象
    Class clazz = Person2.class;
    //获取类的所有公共的构造方法
    Constructor[] constructors = clazz.getConstructors();
    for (Constructor con :
    constructors) {
    System.out.println(con);
    }
    System.out.println("===");
    //获取类的所有的声明的构造方法
    Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
    for (Constructor con :
    declaredConstructors ) {
    System.out.println(con);
    }
    //根据参数获取指定的构造方法
    System.out.println("获取指定一个参数的公共的构造方法:");
    Constructor con1 = clazz.getConstructor(String.class);
    System.out.println(con1);
    System.out.println("获取两个参数的私有的构造方法:");
    Constructor con2 = clazz.getDeclaredConstructor(String.class, int.class);
    System.out.println(con2);
    }
    }

      3.利用Class对象获取类的方法

    创建Person3.java

    package com.aaa.spring.entity;
    public class Person3 {
    public void info(){
    System.out.println("我是一个无参的公共方法");
    }
    public void info(String name,int age){
    System.out.println("我是一个有两个参数的额公共方法");
    }
    private void info(String name){
    System.out.println("我是一个有一个参数的私有的方法");
    }
    }
    /**
    * 利用Class对象获取方法
    */
    public class Test04 {
    public static void main(String[] args) throws Exception {
    //获取类的Class对象
    Class clazz = Person3.class;
    Method[] methods = clazz.getMethods();
    System.out.println("获取类的所有的公共的方法,包含父类的方法:");
    for (Method method:
    methods) {
    System.out.println(method);
    }
    System.out.println("获取所有的声明的方法:");
    Method[] declaredMethods = clazz.getDeclaredMethods();
    for (Method method:
    declaredMethods) {
    System.out.println(method);
    }
    System.out.println("获取两个参数的公共的方法:");
    Method method = clazz.getMethod("info",String.class,int.class);
    System.out.println(method);
    System.out.println("获取一个参数的私有的方法:");
    Method method2 = clazz.getDeclaredMethod("info",String.class);
    System.out.println(method2);
    }
    }

      4.利用Class对象获取类的属性

    创建Person4.java

    package com.aaa.spring.entity;
    public class Person4 extends Person{
    public String name;
    private int age;
    }
    public class Test05 {
    public static void main(String[] args) throws
    Exception{
    //获取类的Class对象
    Class clazz = Person4.class;
    System.out.println("获取类的所有公共的属性(也包括父类中的公共的属性):");
    Field[] fields = clazz.getFields();
    for (Field field :
    fields) {
    System.out.println(field);
    }
    System.out.println("获取类的所有声明的属性:");
    Field[] declaredFields = clazz.getDeclaredFields();
    for (Field field:
    declaredFields ) {
    System.out.println(field);
    }
    //获取公共的name属性
    System.out.println("获取公共的name属性");
    Field name = clazz.getField("name");
    System.out.println(name);
    System.out.println("获取私有的age属性:");
    Field age = clazz.getDeclaredField("age");
    System.out.println(age);
    }
    }

      5.利用Class对象创建类的实例

    创建Person5.java

    package com.aaa.spring.entity;
    public class Person5 {
    private String name;
    //默认无参的构造
    public Person5(){}
    //公共的有一个参数的方法
    public Person5(String name){
    this.name=name;
    }
    //私有的有两个参数的方法
    private Person5(String name,int age){}
    public void info(){
    System.out.println(name);
    }
    }
    /**
    * 利用CLass对象创建类的实例
    */
    public class Test06 {
    public static void main(String[] args) throws Exception {
    //获取类的class对象
    Class clazz = Class.forName("com.aaa.spring.entity.Person5");
    //创建类的对象有两种方式
    //第一种,调用Class对象的newInstance方法,该方法会会调用类的默认的无参的构造
    Person5 person51 =(Person5) clazz.newInstance();
    System.out.println(person51);
    //第二种,根据类的构造方法对象创建类的实例
    Constructor constructor = clazz.getConstructor(String.class);
    Person5 person52 = (Person5)constructor.newInstance("zhangsan");
    System.out.println(person52);
    person52.info();
    Constructor con2 = clazz.getDeclaredConstructor(String.class, int.class);
    //设置忽略构造方法的访问级别
    con2.setAccessible(true);
    Person5 person53 = (Person5)con2.newInstance("zhangsan", 18);
    person53.info();
    }
    }

      6.利用Class对象调用类的方法

    创建Person6.java

    package com.aaa.spring.entity;
    public class Person6 {
    public void info(){
    System.out.println("我是一个无参的公共方法");
    }
    public void info(String name,int age){
    System.out.println("我是一个有两个参数的额公共方法");
    }
    private void info(String name){
    System.out.println("我是一个有一个参数的私有的方法");
    }
    }
    /**
    * 利用Class对象访问类的方法
    */
    public class Test07 {
    public static void main(String[] args) throws Exception {
    Person6 p6 = new Person6();
    p6.info();
    p6.info("zhangsan",12);
    //获取类的Class对象
    Class clazz = Class.forName("com.aaa.spring.entity.Person6");
    //利用反射创建对象
    Object p61 = clazz.newInstance();
    //获取info()方法
    Method info = clazz.getMethod("info");
    //调用用法
    info.invoke(p61);
    //获取info(string,int)这个方法
    Method info1 = clazz.getMethod("info", String.class, int.class);
    //调用方法
    info1.invoke(p61,"张三",16);
    //利用反射调用类的私有的方法
    Method info2 = clazz.getDeclaredMethod("info",String.class);
    //忽略方法的访问级别
    info2.setAccessible(true);
    //调用方法
    info2.invoke(p61,"李四");
    }
    }

      7.利用Class对象返回类的属性

    创建Person7.java

    package com.aaa.spring.entity;
    public class Person7 {
    public String name="zhangsan";
    private int age=12;
    }
    /**
    * 利用Class对象访问类的属性
    */
    public class Test08 {
    public static void main(String[] args) throws Exception {
    Person7 p = new Person7();
    String name = p.name;
    System.out.println(name);
    p.name="lisi";
    System.out.println(p.name);
    //获取类的CLass对象
    Class clazz = Class.forName("com.aaa.spring.entity.Person7");
    //获取对象的属性值,打印出来
    //创建对象
    Object p1 = clazz.newInstance();
    //获取类的属性的对象
    Field f1 = clazz.getField("name");
    //设置属性的值
    f1.set(p1,"lisi");
    //获取属性的值
    Object name1 = f1.get(p1);
    System.out.println(name1.toString());
    Field f2 = clazz.getDeclaredField("age");
    //忽略访问级别
    f2.setAccessible(true);
    System.out.println(f2.get(p1));
    }
    }

     

    转载于:https://www.cnblogs.com/duguangming/p/10913896.html

    展开全文
  • 简单工厂模式

    2010-11-16 11:48:04
    工厂模式的几种形态:简单工厂、工厂方法(多态性工厂、虚拟构造子)、抽象工厂。   简单工厂模式就是由一个工厂类根据传入的参量决定创建一种产品类的实例。   简单工厂模式涉及到的角色:工厂、抽象产品,...
  • 简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定...工厂模式有以下几种形态:(1)简单工厂(Simple Factory)模式,又称静态工厂方法模式(Sta...
  • [说明]简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。 简单工厂模式是由一个工厂对象决定创建出...工厂模式有以下几种形态:简单工厂(Simple Factory)模式,又称静态工厂方法
  • 简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建一种产品类的实例。 1.工厂模式的几种形态 工厂模式专门负责将大量有共同接口的类...
  • 简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定...工厂模式有以下几种形态:(1)简单工厂(Simple Factory)模式,又称静态工厂方法模式(Sta...
  • 模式简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。 简单工厂模式是由一个工厂对象决定创建一种产品类的实例。12.1 工厂模式的几种形态工厂模式专门负责将大量有共同接口的类...
  •  工厂模式大家都非常熟悉包括常用的简单工厂、工厂方法、和抽象工厂等几种。总的来说应该这样定义:定义一个通用的接口用来创建对象。无论是使用一种工厂模式目的都相同,就是“把对象的创建和对象的使用过程...
  • 设计模式之工厂模式

    2015-03-04 00:52:31
    要想搞Java,设计模式是必须要搞明白的,至少几种常用到的模式能想到并运用起来。 首先来说一说简单工厂模式,简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个...
  • Java基础 200317

    2020-03-12 10:43:43
    3. 创建线程池有哪几种方式? 4. 创建线程池的各个参数代表的含义? 【Java 面试点事】 这里致力于分享 Java 面试路上的各种知识,无论是技术还是经验,你需要的这里都有! 这里可以让你【快速了解 Java 相关...
  • 类工厂的使用

    千次阅读 2007-05-10 13:42:00
    工厂模式大家都非常熟悉包括常用的简单工厂、工厂方法、和抽象工厂等几种。总的来说应该这样定义:定义一个通用的接口用来创建对象。无论是使用一种工厂模式目的都相同,就是“把对象的创建和对象的使用过程分离...
  • 2.图像与文本对齐方式有哪几种? 3.项目列表和编号有何区别?分别适用于什么场合? 4.链接到其他页面时,路径的表示方法有两种:相对路径和绝对路径,这两种路径有何区别和联系? 5.创建表格表格最少需要...
  • 下面就介绍几种常用的设计模式,下次再开发的时候,当遇到此类的情况就能知道到底是一种设计模式。 1.单例模式:instance,多态的体现。 单例模式顾名思义,就是只有一个实例。作为对象的创建模式, 单例模式...
  • 类工厂的使用

    2007-02-08 20:30:00
    工厂模式大家都非常熟悉包括常用的简单工厂、工厂方法、和抽象工厂等几种。总的来说应该这样定义:定义一个通用的接口用来创建对象。无论是使用一种工厂模式目的都相同,就是“把对象的创建和对象的使用过程分离...
  • Javascript和HTML dom

    2015-10-20 20:06:00
    其中原始类型又包括以下几种类型:数字型、字符串型、布尔值、null和undefined。其中对象类型包括用户通过各种方法自己创建的对象和一些函数数组啊之类的特殊对象。 然后,我就在思考那么DOM对象属于这里面的一类...
  • 工厂模式大家都非常熟悉包括常用的简单工厂、工厂方法、和抽象工厂等几种。总的来说应该这样定义:定义一个通用的接口用来创建对象。无论是使用一种工厂模式目的都相同,就是“把对象的创建和对象的使用过程分离...
  • 工厂设计模式专门负责将大量有共同接口的类实例化,工厂模式可以动态的决定将一个类实例化,不必事先知道每次要实例化一个类,工厂模式有以下几种形态: 一、简单工厂模式 简介 ​ 简单工厂模式(Simple ...
  • UML建模练习题

    2020-11-09 14:18:20
    UMLUML建模1. UML的三个主要的特性2. UML是一风法论吗?...10. 敏捷UP方法在组织需求时主要的关键制品有那几个11. 候选用例选择的判断准则12. 什么是领域模型?如何创建领域模型,如何找到概念类13. UML中有
  • java面试宝典

    2013-02-28 16:04:01
    184、Servlet执行时一般实现哪几方法? 44 185、getServletContext()和getServletConfig()的意思 44 186、Hashtable和HashMap 44 187、JAVA SERVLET API中forward() 与redirect()的区别? 44 189、Can a Java ...
  • 千方百计笔试题大全

    2011-11-30 21:58:33
    184、Servlet执行时一般实现哪几方法? 44 185、getServletContext()和getServletConfig()的意思 44 186、Hashtable和HashMap 44 187、JAVA SERVLET API中forward() 与redirect()的区别? 44 189、Can a Java ...
  • 最新Java面试宝典pdf版

    热门讨论 2011-08-31 11:29:22
    10、排序都有哪几种方法?请列举。用JAVA实现一个快速排序。 79 11、有数组a[n],用java代码将数组元素顺序颠倒 80 12.金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一千零一拾一元整)输出...
  • Java面试宝典2010版

    2011-06-27 09:48:27
    10、排序都有哪几种方法?请列举。用JAVA实现一个快速排序。 11、有数组a[n],用java代码将数组元素顺序颠倒 80 12.金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一千零一拾一元整)输出。 ...
  • 10、排序都有哪几种方法?请列举。用JAVA实现一个快速排序。 79 11、有数组a[n],用java代码将数组元素顺序颠倒 80 12.金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一千零一拾一元整)输出...
  • 4.4.6 你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms和G1,包括原理,流程,优缺点。 4.4.7 垃圾回收算法的实现原理。 4.4.8 当出现了内存溢出,你怎么排错。 4.4.9 JVM内存模型的相关知识了解多少,比如重...
  • c#学习笔记.txt

    热门讨论 2008-12-15 14:01:21
    另外我发现论坛上学习Java的人都非常的有个性,当有人问起学习哪种语言更好时,他会打出百个“JAVA”来,填满整个屏幕,也不说是为了什么。我觉得这样做未免有些太霸道了,如果你说这叫偏执狂我也不反对,虽然我...

空空如也

空空如也

1 2 3 4 5
收藏数 84
精华内容 33
关键字:

创建那哪几种方法