つくねの手帳

C++およびAndroidアプリ開発メインで何か書きたい

Java覚書:Serializable

  • java.io.Serializableインターフェース

Javaでは、DBへの保存やファイル出力を行う際に、java.io.Serializableインターフェースを実装したクラスを使います。
このインターフェースを実装することで、シリアライズ/デシリアライズが可能になります。実装していない場合はシリアライズ/デシリアライズされることはありません。

例:

import java.io.Serializable;

public class SampleData implements Serializable {
  private static final long serialVarsionUID = 1L;

  private String name;

  public String getName(){
    return name;
  }

  public void setName(String data){
    name = data;
  }
}

このインターフェース、上の例を見てもわかる通り、オーバーライドするべき関数はありませんし、フィールドもありません。
単純に、シリアライズ/デシリアライズが可能であることを示すための宣言として機能します。

注意事項として、内部に持つフィールドは、プリミティブ型もしくはシリアライズ可能なクラスである必要があります。

  • シリアルバージョンID

例のクラスに書かれている、

private static final long serialVarsionUID = 1L;

この定義はシリアルバージョンIDで、シリアライズ/デシリアライズの前後でクラスのバージョンが異なっていないかを識別するために定義しています。
serialVersionUIDを定義しておくことで、バージョンが不一致の際にInvalidClassExceptionの例外を投げてくれます。
明示的に宣言をしていない場合でもデフォルト値を計算してくれますが、コンパイラの実装次第で予期しない不一致が発生する可能性があります。
コンパイラが異なっても一貫性を保つために、明示的に宣言することが推奨されています。

6年目エンジニアの転職記

2017年12月で5年半ほどお世話になった会社を退職し、2018年1月から新しい会社で働いています。

初転職の所感としてはやはり売り手市場というか、どこの企業も人手が欲しい感じを受けました。
今回は実際に使ったサービスや感想などを簡単にまとめたいと思います。

転職エージェント・サービス

主に使用したのは以下の3つです。
これ以外にもいくつかのエージェントと話をしましたが、いまいちしっくり来なかったので見送りました。
エージェントについては合う合わないがあるので、自分がやりやすく信頼できる所を見つけたほうがいいと思います。
あと、エージェントを増やしすぎるのはオススメしません。自分が管理しきれなくなります。3つでも結構大変でした。


①レバテック

  • 個人担当と個別企業担当がいる。*1
  • 求人情報等はGoogleスプレッドシートで管理される。*2
  • 面接対策用の資料が充実している。
  • 個人担当と企業担当が別が故のデメリットが発生することがある。*3


②ビズリーチ

  • CMでおなじみのやつ
  • 結構手軽で登録するだけで求人がわんさか来る。*4
  • 個別の面接対策とかはない。*5


③@Type転職

  • 転職先を紹介するというより、この先のキャリアについて考えさせてくれた。*6
  • 大きい企業の求人を結構持っている印象。
  • 書類の添削が丁寧。

ハローワーク

  • 実際ほとんど使ってない。無職になってしまった場合の給付とかの話を聞きに行った。
  • 求人検索用端末のUIが使いにくすぎてつらかった。
転職活動に関して

今回初めての転職に際して、準備したこと、転職活動中の所感などを書きます。

  • 準備

私は転職を考えてから実際に行動するまで、約10か月ほど時間がかかりました。
その間に準備として、自分のスキルの棚卸、業界の動向調査などは意識的に行いました。

現職の環境がひどい場合はその限りではありませんが、転職に踏み切る際にはある程度準備をしておくほうがよいです。
よく取りあげられていますが、自分のスキルの棚卸はおススメです。
自分の出来ること、足りないこと共に再認識できるので、転職するしないに関わらず私も定期的に行っていこうと思っています。

  • 転職活動中

実業務と転職活動を並行して行うので、結構疲れます。
私が思っていたよりかなりスピーディーに選考が進みました。
また、複数企業一斉に選考が進むので、スケジュール管理がなかなか大変でした。

大変ではありますが、いろいろな企業の方と話が出来るのはいい体験でした。

  • 転職後

やはり新しい環境で働くというのはエネルギーを使います。
社歴は1年目になりますが、エンジニアとしては経験者なので、ある程度の能力は求められます。
不慣れであったり、人間関係も築けていない状態で思うようにアウトプット出来ない自分に、もどかしさも感じました。
しかし、新しい人たちと働くことで、新たな考え方や技術に触れられるというのは大きなプラスになっています。

まとめ

実際に選考を受けてみて、私の予想以上に選択肢は広いんだなぁと感じました。
自分のスキルを活かせる新たな業界も観ることができました。
現職では出来ないがやりたいことがある人、行きたい企業がある人、思い切って飛び込んで見てもいいかもしれません。

転職するか悩んでいる人は、とりあえず準備を進めておくというのがいいかもしれません。
求人とかを見てみるだけでも待遇面や、メインの技術などはある程度つかめます。

*1:個人担当が日程調整や求人紹介をしてくれて、企業担当が面接対策とかをしてくれます。

*2:実際私はほとんど使いませんでした。

*3:個人担当と企業担当の意思疎通がうまくいっていない事が少し見られました。

*4:企業から直接面接オファーがくる場合と、転職エージェントが声をかけてくる場合があります。登録しているスキル、現年収、自己PRの内容にもよると思いますが、転職エージェントからの連絡が多めでした。③の@Type転職はビズリーチ経由で話を聞きに行きました。

*5:企業からの面接オファーなので当然期待できないです。

*6:今回の転職というより、この先エンジニアとしてどうなって行きたいかを面談で話し合ってくれました。

Widgetの回転と枠線について

今回は、組み込み開発などにおいて、LCDの関係などでWidgetを回転させたい。という時に、QGraphicsSceneとQGtaphicsViewを用いた回転方法と、その際にWidgetに対してついてしまう枠線について書きたいと思います。

例によって、Qtのversionは4.8です。

先ず、Widgetの回転についてです。
Widgetの回転は、対象のWidgetをQGraphicsSceneへ渡し、そのQGraphicsSceneをQGraphicsViewへ登録。QGraphicsViewのrotate関数で実現できます。

  QGraphicsScene *scene = new QGraphicsScene();
  scene->addWidget(/*回転させたいWidgetハンドル*/);

  QGraphicsView *view = new QGraphicsView(scene); // QGraphicsViewにsceneを登録
  view->rotate(90); // 90度回転

これで対象のWidgetを回転させられたかと思います。
ただ、このままだとWidgetに1pxの枠線がついてしまうと思います。

  setWindowFlags(Qt::FramelessWindowHint);

などをWidgetに指定しても、消せないのですが、これには理由があります。

先程、回転のためにQGraphicsViewを使用しました。
このクラスは親クラスをたどるとQFrameクラスを継承しています。
その為デフォルト1pxの枠線を描画してしまいます。
枠線を描画したくない場合は、以下のようにQGraphicsViewにオプション指定をしましょう。

  view->setFrameShape(QFrame::NoFrame);

こうすることで、もとのイメージのまま回転が可能です。

QtCreatorでデバッグ中にブレークポイントにとまるとアプリがクラッシュする

この現象はQtCreator2.5.2という古いバージョンで発生したものなので、現在のQtCreatorでは発生しないかもしれません。

内容はタイトルの通りで、QtCreatorでQtプロジェクトのデバッグ実行中に、特定の場所、タイミングでブレークポイントんとに止まるとアプリがクラッシュするというものです。

結論から言うと、QtCreatorの監視ウィンドウが原因でした。


QtCreatorにはデバッグ中に変数の中身を表示させる監視ウィンドウというものがあります。
中身を見たい変数を右クリックし、「監視ウィンドウに追加」のメニューを選択することで、QtCreatorが変数の中身を表示してくれます。
VisualStudioでいうローカル変数タブのイメージですね。

デバッグ時には便利なのですが、以下のようなコードを監視することで、タイトルの現象が起きてしまいます。

hoge.h

class hoge

public:

  hoge();
  ~hoge();
  
  bool getFirstItem(int* buf); 

private
  QVector<int> m_vector; // メンバ変数にQVectorを定義
hoge.cpp

hoge::hoge()
{
  this->m_vector.clear(); 

  int a = 0;
  this->getFirstItem(&a); // ここにブレークポイントを置くと落ちる。ブレークせずに走らせる場合は問題なし。
}

bool hoge::getFirstItem(int* buf)
{
  bool bRet = false;
  
  if(false == this->m_vector->isEmpty())
  {
    buf = this->m_vector[0]; // ここのthis->m_vector[0]を監視ウィンドウに追加
    bRet = true;
  }

  return bRet;
}


QVectorは可変配列ですが、通常の配列のようにでアクセスが可能です。

当然、Vectorの中身がない場合はエラーになるのですが、上記のようにコード上はチェックをしていても、
監視ウィンドウにm_vector[0]のような変数を追加しておくと、このVectorはメンバ変数なので、クラス内どこでも参照可能です。

そのため、クラス内のブレークポイントに止まった際に、問答無用でアクセスエラーを起こします。

この時に、QtCreatorがエラーログをはいてくれるのですが、"ASSERT failure in QVector::operator:"index out of range",file....."
と配列オーバーアクセスなのはわかるのですが、どこで起きているのかわからないので、コード上を探しても配列オーバーアクセスを起こすコードは見つからない。
ということが起こります。

そもそもVectorにたいして[]でアクセスするな。という話かもしれませんが、ブレークしたときにVectorのアクセスエラーで落ちる。
なんて現象に遭遇した場合は、一度監視ウィンドウをチェックするほうがいいかもしれません。

Android SutudioにKotlinを導入する

先日のGoogle I/OにてKotlinが正式サポートされるということで、以前から興味があったKotlinを導入してみようと思う。

IDEAndroid Studio 2.3.2で行う。

先ずはKotlinのプラグインをインストールする。

File > Settings
からPluginsを選択し、Install JetBrains pluginsを選択する。
f:id:tukunen13:20170603193414p:plain

Browse JetBrains Plugins画面の左上検索バーからKotlinを検索し、
Installを行う。
f:id:tukunen13:20170603193759p:plain


Android Studioを再起動し、ToolsのプルダウンにKotlinの項目が追加されていれば完了。

既存のJavaコードは、Codeのプルダウンから、Convert Java File to Kotlin Fileを選択すると自動的に変換をかけてくれる。

画面上部にKotlin not configuredと表示されていると思うので、Configureボタンをクリックする。
Configure Kotlin ProjectのダイアログはそのままOKをクリック。
これでKotlinでの環境構築は完了となる。

QThreadとWorkerクラスの後処理

Qtでの非同期処理はQThreadクラスと自前のWorkerクラスで以下のように実装できる。

Worker.h

class Worker : public Qobject
{
    Q_OBJECT
public:
    Worker(); // 親を指定してしまうとスレッドに渡せなくなる。
    ~Worker();

public slots:
    // 作業用スロット

};

main.cpp

QThread* workerThread = new QThread(this);
Worker* worker = new Worker();

worker->moveToThread(workerThread);

connect(workerThread , SIGNAL(finished()) , workerThread , SLOT(deleteLater)):
connect(workerThread , SIGNAL(finished()) , worker , SLOT(deleteLater)):
// 作業用スロットのコネクト

workerThread->start();

スレッドに処理を依頼するときは、作業用スロットに対してシグナルを送ってあげることで実行できる。

アプリ終了時等でスレッドを止める際は、

workerThread->quit();

とすることで、QThreadクラスないでfinishedシグナルが発行され、workerクラスとスレッドがdeleteされる。


単発的な処理(ライフサイクルの短いスレッド)の場合は以下のように実装することで、外からQThreadのquit()を呼ぶことなく並列処理を実行できる。

Worker.h

public slots:
    void process();
signals:
    void processEnd();

Worker.cpp

void Worker::process()
{
    // 何かしらの処理

    // 処理終了
    emit this->processEnd():
}

main.cpp

QThread* workerThread = new QThread(this);
Worker* worker = new Worker();

worker->moveToThread(workerThread);

connect(workerThread , SIGNAL(started()) , worker , SLOT(process()));
connect(worker , SIGNAL(processEnd()) , workerThread , SLOT(quit()));
connect(worker , SIGNAL(processEnd()) , worker , SLOT(deleteLater()));
connect(workerThread , SIGNAL(finished()) , workerThread , SLOT(deleteLater()));

workerThread->start();

この場合、startが呼ばれたところからworkerクラスの処理が始まり、終了と同時に、workerクラスのprocessEnd→workerThreadのquit、それぞれのdeleteLaterがコールされ処理が完結する。

この流れをアプリ終了時等、メインスレッド側のデストラクタで呼び出すとスレッドのdeleteLaterによるスレッド削除が実行される前にデストラクタを抜けてしまうようで、QtCreatorのアプリケーション出力に"QThread: Destroyed while thread is still running"と警告される。

QThreadのquit始動でworkerクラスをdeleteする場合は問題ないので、何かしらの解決策がありそうだが、見つかっていない。

QStringからcharポインタを取り出す

今回はちょっとしたTips的な話。

例によってQt4.8環境です。

QStringは文字列をとても簡単に取り扱えるクラスですが、一度文字を渡してしまうと、
charとして取り出すのに一つ関数を余計に挟む必要があります。
取り出し方はこんな感じです。

#include "QString.h"

QString string = "moji";

char* pChar = string.toUtf8().data();


Qtで開発している以上そんなに使用頻度はないかもしれませんが、知ってると便利。